diff --git a/LICENCE b/LICENCE
new file mode 100644
index 0000000..8da7481
--- /dev/null
+++ b/LICENCE
@@ -0,0 +1,24 @@
+opyright (c) 2013, Jeongbin Park
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4c36287
--- /dev/null
+++ b/README.md
@@ -0,0 +1,4 @@
+Cas-Analyzer
+==
+
+Updated soon
diff --git a/core/compile_core.sh b/core/compile_core.sh
new file mode 100755
index 0000000..40dc6a0
--- /dev/null
+++ b/core/compile_core.sh
@@ -0,0 +1,4 @@
+cp jbfilereader/jbfilereader.coffee .
+coffee --bare --compile jbfilereader.coffee
+coffee --bare --compile fastq-join.coffee
+coffee --bare --compile miseq-analyzer.coffee
diff --git a/core/fastq-join-sync.coffee b/core/fastq-join-sync.coffee
new file mode 100644
index 0000000..25b5c73
--- /dev/null
+++ b/core/fastq-join-sync.coffee
@@ -0,0 +1,220 @@
+###
+fastq-join.coffee
+(Based on Fastq-join 1.01 by Expression Analysis / Erik Aronesty)
+
+Copyright (c) 2015 Jeongbin Park
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+###
+
+dev = 0
+joins = []
+#un1s = []
+#un2s = []
+
+class _line
+ constructor: ->
+ this.s = ''
+ this.n = 0
+
+class _fq
+ constructor: ->
+ this.id = new _line
+ this.seq = new _line
+ this.com = new _line
+ this.qual = new _line
+
+comp = (l) ->
+ for i in [0...l.length] by 1
+ if l[i] == 'A'
+ l[i] = 'T'
+ else if l[i] == 'T'
+ l[i] = 'A'
+ else if l[i] == 'G'
+ l[i] = 'C'
+ else if l[i] == 'C'
+ l[i] = 'G'
+ else if l[i] == 'a'
+ l[i] = 't'
+ else if l[i] == 't'
+ l[i] = 'a'
+ else if l[i] == 'g'
+ l[i] = 'c'
+ else if l[i] == 'c'
+ l[i] = 'g'
+ return l
+
+revcomp = (fq) ->
+ fq.seq.s = comp(fq.seq.s).reverse() # Non-unicode aware!
+ fq.qual.s = fq.qual.s.reverse() # Again, non-unicode aware!
+ return fq
+
+min = (a, b) ->
+ if a > b
+ return b
+ else
+ return a
+
+max = (a, b) ->
+ if a < b
+ return b
+ else
+ return a
+
+hd = (a, s, b, n) ->
+ d = 0
+ i = 0
+ while n > 0
+ if a[s+i] != b[i]
+ d++
+ n--
+ i++
+ return d+n
+
+# Third mate file is not supported yet
+run_fastq_join = (files, donecallback, pgcallback, chunkcallback, joinsonly = false, mino = 6, pctdiff = 8) ->
+ dev = 0
+ joincnt = 0
+ tlen = 0
+ tlensq = 0
+ nline = [0, 0]
+ joins = []
+ un1s = []
+ un2s = []
+ fq = [new _fq, new _fq]
+ nrec = 0
+ prevfpos = 0
+ steprec = 50
+
+ readers = [0, 0]
+ for nfin in [0..1] by 1
+ entries = files[nfin].name.split('.')
+ if entries[entries.length-1] == 'gz'
+ gzipped = 1
+ readers[nfin] = new jbfilereader(files[nfin], gzipped)
+
+ read_line = (nfin, l, opt) ->
+ readers[nfin].readline( (line) ->
+ if readers[0].eof or line == ""
+ readers[1].readline( (line2) ->
+ if readers[1].eof or line2 == ""
+ post_loop()
+ else
+ self.postMessage({msgtype: 1, error: "# of rows in mate file doesn't match primary file!"})
+ )
+ else if readers[1].eof and !readers[0].eof
+ self.postMessage({msgtype: 1, error: "# of rows in mate file doesn't match primary file!"})
+ else
+ l.s = line.split("") # To array, because strings are immutable, note that this is not unicode aware!
+ l.n = l.s.length
+ opt++
+ read_fq(opt)
+ )
+ return
+
+ post_loop = ->
+ chunkcallback(joins)
+ pgcallback(100)
+ donecallback()
+ return
+
+ read_fq = (opt) ->
+ for nfin in [0..1] by 1
+ if opt == 0+nfin*4
+ read_line(nfin, fq[nfin].id, opt)
+ return
+ else if opt == 1+nfin*4
+ read_line(nfin, fq[nfin].seq, opt)
+ return
+ else if opt == 2+nfin*4
+ read_line(nfin, fq[nfin].com, opt)
+ return
+ else if opt == 3+nfin*4
+ read_line(nfin, fq[nfin].qual, opt)
+ return
+ if opt == 8
+ #if fq[nfin].id.s[0] == '>'
+ # alert('Input is FASTA!')
+ # return 1
+ if (fq[0].id.n == 0 or (fq[0].id.n != 0 and fq[0].id.s[0] != '@')) or
+ (fq[1].id.n == 0 or (fq[1].id.n != 0 and fq[1].id.s[0] != '@'))
+ self.postMessage({msgtype: 1, error: 'Input file is not FASTQ!'})
+ return 1
+ main_loop()
+ return
+ return
+
+ main_loop = ->
+ nrec++
+ rc = revcomp(fq[1])
+ maxo = min(fq[0].seq.n, rc.seq.n)
+ bestscore = 2147483647 # INT_MAX of C
+ besto = -1
+ for i in [mino..maxo] by 1
+ mind = (pctdiff * i) // 100
+ d = hd(fq[0].seq.s, fq[0].seq.n-i, rc.seq.s, i)
+ if d <= mind
+ score = (1000*(d*d+1)) // i
+ if (score < bestscore)
+ bestscore = score
+ besto = i
+ hasex = 0
+ olen = besto - hasex
+ if besto > 0
+ joincnt++
+
+ tlen += olen
+ tlensq += olen**2
+
+ #joins.push(fq[0].id.s.join("") + "\n")
+ for i in [0...besto] by 1
+ li = fq[0].seq.n-besto+i
+ ri = i
+ if fq[0].seq.s[li] == rc.seq.s[ri]
+ fq[0].qual.s[li] = String.fromCharCode(max(fq[0].qual.s[li].charCodeAt(0), rc.qual.s[ri].charCodeAt(0)))
+ else
+ if fq[0].qual.s[li].charCodeAt(0) > rc.qual.s[ri].charCodeAt(0)
+ fq[0].qual.s[li] = String.fromCharCode(33+min(fq[0].qual.s[li].charCodeAt(0),max(fq[0].qual.s[li].charCodeAt(0)-rc.qual.s[ri].charCodeAt(0),3)))
+ else
+ fq[0].seq.s[li] = rc.seq.s[ri]
+ fq[0].qual.s[li] = String.fromCharCode(33+min(rc.qual.s[ri].charCodeAt(0),max(rc.qual.s[ri].charCodeAt(0)-fq[0].qual.s[li].charCodeAt(0),3)))
+ joins.push(fq[0].seq.s.join("") + rc.seq.s[besto..].join("") + "\n")
+ #joins.push(fq[0].com.s.join("") + "\n")
+ #joins.push(fq[0].qual.s.join("") + rc.qual.s[besto..].join("") + "\n")
+ #else if !joinsonly
+ # un1s.push(fq[0].id.s.join("") + "\n")
+ # un1s.push(fq[0].seq.s.join("") + "\n")
+ # un1s.push(fq[0].com.s.join("") + "\n")
+ # un1s.push(fq[0].qual.s.join("") + "\n")
+ # un2s.push(fq[1].id.s.join("") + "\n")
+ # un2s.push(fq[1].seq.s.join("") + "\n")
+ # un2s.push(fq[1].com.s.join("") + "\n")
+ # un2s.push(fq[1].qual.s.join("") + "\n")
+ if nrec %% steprec == 0
+ if prevfpos != readers[0].fpos
+ pgcallback(readers[0].fpos*100/files[0].size)
+ chunkcallback(joins)
+ joins = []
+ prevfpos = readers[0].fpos
+ setTimeout( ( -> read_fq(0)), 0)
+ else
+ read_fq(0)
+ return
+ setTimeout( ( -> read_fq(0)), 0)
+ return
diff --git a/core/fastq-join.coffee b/core/fastq-join.coffee
new file mode 100644
index 0000000..22f5ffc
--- /dev/null
+++ b/core/fastq-join.coffee
@@ -0,0 +1,208 @@
+###
+fastq-join.coffee
+(Based on Fastq-join 1.01 by Expression Analysis / Erik Aronesty)
+
+Copyright (c) 2015 Jeongbin Park
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+###
+
+dev = 0
+joins = []
+#un1s = []
+#un2s = []
+
+class _line
+ constructor: ->
+ this.s = ''
+ this.n = 0
+
+class _fq
+ constructor: ->
+ this.id = new _line
+ this.seq = new _line
+ this.com = new _line
+ this.qual = new _line
+
+comp = (l) ->
+ for i in [0...l.length] by 1
+ if l[i] == 'A'
+ l[i] = 'T'
+ else if l[i] == 'T'
+ l[i] = 'A'
+ else if l[i] == 'G'
+ l[i] = 'C'
+ else if l[i] == 'C'
+ l[i] = 'G'
+ else if l[i] == 'a'
+ l[i] = 't'
+ else if l[i] == 't'
+ l[i] = 'a'
+ else if l[i] == 'g'
+ l[i] = 'c'
+ else if l[i] == 'c'
+ l[i] = 'g'
+ return l
+
+revcomp = (fq) ->
+ fq.seq.s = comp(fq.seq.s).reverse() # Non-unicode aware!
+ fq.qual.s = fq.qual.s.reverse() # Again, non-unicode aware!
+ return fq
+
+min = (a, b) ->
+ if a > b
+ return b
+ else
+ return a
+
+max = (a, b) ->
+ if a < b
+ return b
+ else
+ return a
+
+hd = (a, s, b, n) ->
+ d = 0
+ i = 0
+ while n > 0
+ if a[s+i] != b[i]
+ d++
+ n--
+ i++
+ return d+n
+
+# Third mate file is not supported yet
+run_fastq_join = (files, pgcallback, chunkcallback, joinsonly = false, mino = 6, pctdiff = 8) ->
+ dev = 0
+ joincnt = 0
+ tlen = 0
+ tlensq = 0
+ nline = [0, 0]
+ joins = []
+ un1s = []
+ un2s = []
+ fq = [new _fq, new _fq]
+ nrec = 0
+ prevfpos = 0
+ steprec = 500
+
+ readers = [0, 0]
+ for nfin in [0..1] by 1
+ entries = files[nfin].name.split('.')
+ if entries[entries.length-1] == 'gz'
+ gzipped = 1
+ else
+ gzipped = 0
+ readers[nfin] = new jbfilereadersync(files[nfin], gzipped)
+
+ read_fq = () ->
+ eofs = [false, false]
+ for nfin in [0..1] by 1
+ for type in [0..3] by 1
+ try
+ line = readers[nfin].readline()
+ if line == ""
+ eofs[nfin] = true
+ break
+ catch e
+ self.postMessage({msgtype: 1, error: e})
+ return 2
+ if type == 0
+ fq[nfin].id.s = line.split("")
+ fq[nfin].id.n = fq[nfin].id.s.length
+ else if type == 1
+ fq[nfin].seq.s = line.split("")
+ fq[nfin].seq.n = fq[nfin].seq.s.length
+ else if type == 2
+ fq[nfin].com.s = line.split("")
+ fq[nfin].com.n = fq[nfin].com.s.length
+ else if type == 3
+ fq[nfin].qual.s = line.split("")
+ fq[nfin].qual.n = fq[nfin].qual.s.length
+ if (fq[nfin].id.n == 0 or (fq[nfin].id.n != 0 and fq[nfin].id.s[0] != '@'))
+ self.postMessage({msgtype: 1, error: "Input file is not FASTQ!"})
+ return 2
+ if (eofs[0] == true and eofs[1] == false) or (eofs[0] == false and eofs[1] == true)
+ self.postMessage({msgtype: 1, error: "# of rows in mate file doesn't match primary file!"})
+ return 2
+ else if eofs[0] == true and eofs[1] == true
+ return 1
+ else
+ return 0
+
+ loop
+ nrec++
+ rtn = read_fq()
+ if rtn == 1
+ break
+ else if rtn == 2
+ return
+ rc = revcomp(fq[1])
+ maxo = min(fq[0].seq.n, rc.seq.n)
+ bestscore = 2147483647 # INT_MAX of C
+ besto = -1
+ for i in [mino..maxo] by 1
+ mind = (pctdiff * i) // 100
+ d = hd(fq[0].seq.s, fq[0].seq.n-i, rc.seq.s, i)
+ if d <= mind
+ score = (1000*(d*d+1)) // i
+ if (score < bestscore)
+ bestscore = score
+ besto = i
+ hasex = 0
+ olen = besto - hasex
+ if besto > 0
+ joincnt++
+
+ tlen += olen
+ tlensq += olen**2
+
+ #joins.push(fq[0].id.s.join("") + "\n")
+ for i in [0...besto] by 1
+ li = fq[0].seq.n-besto+i
+ ri = i
+ if fq[0].seq.s[li] == rc.seq.s[ri]
+ fq[0].qual.s[li] = String.fromCharCode(max(fq[0].qual.s[li].charCodeAt(0), rc.qual.s[ri].charCodeAt(0)))
+ else
+ if fq[0].qual.s[li].charCodeAt(0) > rc.qual.s[ri].charCodeAt(0)
+ fq[0].qual.s[li] = String.fromCharCode(33+min(fq[0].qual.s[li].charCodeAt(0),max(fq[0].qual.s[li].charCodeAt(0)-rc.qual.s[ri].charCodeAt(0),3)))
+ else
+ fq[0].seq.s[li] = rc.seq.s[ri]
+ fq[0].qual.s[li] = String.fromCharCode(33+min(rc.qual.s[ri].charCodeAt(0),max(rc.qual.s[ri].charCodeAt(0)-fq[0].qual.s[li].charCodeAt(0),3)))
+ joins.push(fq[0].seq.s.join("") + rc.seq.s[besto..].join("") + "\n")
+ #joins.push(fq[0].com.s.join("") + "\n")
+ #joins.push(fq[0].qual.s.join("") + rc.qual.s[besto..].join("") + "\n")
+ #else if !joinsonly
+ # un1s.push(fq[0].id.s.join("") + "\n")
+ # un1s.push(fq[0].seq.s.join("") + "\n")
+ # un1s.push(fq[0].com.s.join("") + "\n")
+ # un1s.push(fq[0].qual.s.join("") + "\n")
+ # un2s.push(fq[1].id.s.join("") + "\n")
+ # un2s.push(fq[1].seq.s.join("") + "\n")
+ # un2s.push(fq[1].com.s.join("") + "\n")
+ # un2s.push(fq[1].qual.s.join("") + "\n")
+ if nrec %% steprec == 0
+ if prevfpos != readers[0].fpos
+ pgcallback(readers[0].fpos*100/files[0].size)
+ chunkcallback(joins)
+ joins = []
+ prevfpos = readers[0].fpos
+ chunkcallback(joins)
+ pgcallback(100)
+ return
diff --git a/core/fastq-join.js b/core/fastq-join.js
new file mode 100644
index 0000000..6586b3e
--- /dev/null
+++ b/core/fastq-join.js
@@ -0,0 +1,258 @@
+// Generated by CoffeeScript 1.8.0
+
+/*
+fastq-join.coffee
+(Based on Fastq-join 1.01 by Expression Analysis / Erik Aronesty)
+
+Copyright (c) 2015 Jeongbin Park
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+ */
+var comp, dev, hd, joins, max, min, revcomp, run_fastq_join, _fq, _line,
+ __modulo = function(a, b) { return (+a % (b = +b) + b) % b; };
+
+dev = 0;
+
+joins = [];
+
+_line = (function() {
+ function _line() {
+ this.s = '';
+ this.n = 0;
+ }
+
+ return _line;
+
+})();
+
+_fq = (function() {
+ function _fq() {
+ this.id = new _line;
+ this.seq = new _line;
+ this.com = new _line;
+ this.qual = new _line;
+ }
+
+ return _fq;
+
+})();
+
+comp = function(l) {
+ var i, _i, _ref;
+ for (i = _i = 0, _ref = l.length; _i < _ref; i = _i += 1) {
+ if (l[i] === 'A') {
+ l[i] = 'T';
+ } else if (l[i] === 'T') {
+ l[i] = 'A';
+ } else if (l[i] === 'G') {
+ l[i] = 'C';
+ } else if (l[i] === 'C') {
+ l[i] = 'G';
+ } else if (l[i] === 'a') {
+ l[i] = 't';
+ } else if (l[i] === 't') {
+ l[i] = 'a';
+ } else if (l[i] === 'g') {
+ l[i] = 'c';
+ } else if (l[i] === 'c') {
+ l[i] = 'g';
+ }
+ }
+ return l;
+};
+
+revcomp = function(fq) {
+ fq.seq.s = comp(fq.seq.s).reverse();
+ fq.qual.s = fq.qual.s.reverse();
+ return fq;
+};
+
+min = function(a, b) {
+ if (a > b) {
+ return b;
+ } else {
+ return a;
+ }
+};
+
+max = function(a, b) {
+ if (a < b) {
+ return b;
+ } else {
+ return a;
+ }
+};
+
+hd = function(a, s, b, n) {
+ var d, i;
+ d = 0;
+ i = 0;
+ while (n > 0) {
+ if (a[s + i] !== b[i]) {
+ d++;
+ }
+ n--;
+ i++;
+ }
+ return d + n;
+};
+
+run_fastq_join = function(files, pgcallback, chunkcallback, joinsonly, mino, pctdiff) {
+ var besto, bestscore, d, entries, fq, gzipped, hasex, i, joincnt, li, maxo, mind, nfin, nline, nrec, olen, prevfpos, rc, read_fq, readers, ri, rtn, score, steprec, tlen, tlensq, un1s, un2s, _i, _j, _k;
+ if (joinsonly == null) {
+ joinsonly = false;
+ }
+ if (mino == null) {
+ mino = 6;
+ }
+ if (pctdiff == null) {
+ pctdiff = 8;
+ }
+ dev = 0;
+ joincnt = 0;
+ tlen = 0;
+ tlensq = 0;
+ nline = [0, 0];
+ joins = [];
+ un1s = [];
+ un2s = [];
+ fq = [new _fq, new _fq];
+ nrec = 0;
+ prevfpos = 0;
+ steprec = 500;
+ readers = [0, 0];
+ for (nfin = _i = 0; _i <= 1; nfin = _i += 1) {
+ entries = files[nfin].name.split('.');
+ if (entries[entries.length - 1] === 'gz') {
+ gzipped = 1;
+ } else {
+ gzipped = 0;
+ }
+ readers[nfin] = new jbfilereadersync(files[nfin], gzipped);
+ }
+ read_fq = function() {
+ var e, eofs, line, type, _j, _k;
+ eofs = [false, false];
+ for (nfin = _j = 0; _j <= 1; nfin = _j += 1) {
+ for (type = _k = 0; _k <= 3; type = _k += 1) {
+ try {
+ line = readers[nfin].readline();
+ if (line === "") {
+ eofs[nfin] = true;
+ break;
+ }
+ } catch (_error) {
+ e = _error;
+ self.postMessage({
+ msgtype: 1,
+ error: e
+ });
+ return 2;
+ }
+ if (type === 0) {
+ fq[nfin].id.s = line.split("");
+ fq[nfin].id.n = fq[nfin].id.s.length;
+ } else if (type === 1) {
+ fq[nfin].seq.s = line.split("");
+ fq[nfin].seq.n = fq[nfin].seq.s.length;
+ } else if (type === 2) {
+ fq[nfin].com.s = line.split("");
+ fq[nfin].com.n = fq[nfin].com.s.length;
+ } else if (type === 3) {
+ fq[nfin].qual.s = line.split("");
+ fq[nfin].qual.n = fq[nfin].qual.s.length;
+ }
+ }
+ if (fq[nfin].id.n === 0 || (fq[nfin].id.n !== 0 && fq[nfin].id.s[0] !== '@')) {
+ self.postMessage({
+ msgtype: 1,
+ error: "Input file is not FASTQ!"
+ });
+ return 2;
+ }
+ }
+ if ((eofs[0] === true && eofs[1] === false) || (eofs[0] === false && eofs[1] === true)) {
+ self.postMessage({
+ msgtype: 1,
+ error: "# of rows in mate file doesn't match primary file!"
+ });
+ return 2;
+ } else if (eofs[0] === true && eofs[1] === true) {
+ return 1;
+ } else {
+ return 0;
+ }
+ };
+ while (true) {
+ nrec++;
+ rtn = read_fq();
+ if (rtn === 1) {
+ break;
+ } else if (rtn === 2) {
+ return;
+ }
+ rc = revcomp(fq[1]);
+ maxo = min(fq[0].seq.n, rc.seq.n);
+ bestscore = 2147483647;
+ besto = -1;
+ for (i = _j = mino; _j <= maxo; i = _j += 1) {
+ mind = Math.floor((pctdiff * i) / 100);
+ d = hd(fq[0].seq.s, fq[0].seq.n - i, rc.seq.s, i);
+ if (d <= mind) {
+ score = Math.floor((1000 * (d * d + 1)) / i);
+ if (score < bestscore) {
+ bestscore = score;
+ besto = i;
+ }
+ }
+ }
+ hasex = 0;
+ olen = besto - hasex;
+ if (besto > 0) {
+ joincnt++;
+ tlen += olen;
+ tlensq += Math.pow(olen, 2);
+ for (i = _k = 0; _k < besto; i = _k += 1) {
+ li = fq[0].seq.n - besto + i;
+ ri = i;
+ if (fq[0].seq.s[li] === rc.seq.s[ri]) {
+ fq[0].qual.s[li] = String.fromCharCode(max(fq[0].qual.s[li].charCodeAt(0), rc.qual.s[ri].charCodeAt(0)));
+ } else {
+ if (fq[0].qual.s[li].charCodeAt(0) > rc.qual.s[ri].charCodeAt(0)) {
+ fq[0].qual.s[li] = String.fromCharCode(33 + min(fq[0].qual.s[li].charCodeAt(0), max(fq[0].qual.s[li].charCodeAt(0) - rc.qual.s[ri].charCodeAt(0), 3)));
+ } else {
+ fq[0].seq.s[li] = rc.seq.s[ri];
+ fq[0].qual.s[li] = String.fromCharCode(33 + min(rc.qual.s[ri].charCodeAt(0), max(rc.qual.s[ri].charCodeAt(0) - fq[0].qual.s[li].charCodeAt(0), 3)));
+ }
+ }
+ }
+ joins.push(fq[0].seq.s.join("") + rc.seq.s.slice(besto).join("") + "\n");
+ }
+ if (__modulo(nrec, steprec) === 0) {
+ if (prevfpos !== readers[0].fpos) {
+ pgcallback(readers[0].fpos * 100 / files[0].size);
+ chunkcallback(joins);
+ joins = [];
+ prevfpos = readers[0].fpos;
+ }
+ }
+ }
+ chunkcallback(joins);
+ pgcallback(100);
+};
diff --git a/core/jbfilereader b/core/jbfilereader
new file mode 160000
index 0000000..973b960
--- /dev/null
+++ b/core/jbfilereader
@@ -0,0 +1 @@
+Subproject commit 973b960048f6a539a0fe8422c2444fc67f139b70
diff --git a/core/jbfilereader.coffee b/core/jbfilereader.coffee
new file mode 100644
index 0000000..8b72170
--- /dev/null
+++ b/core/jbfilereader.coffee
@@ -0,0 +1,207 @@
+###
+jbfilereader.coffee
+
+Copyright (c) 2015 Jeongbin Park
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+###
+
+class _inflater
+ constructor: ->
+ window_bits = 15
+ enable_windows_gzip = 32
+ @inflater_pako = new pako.Inflate({to: 'string', chunkSize: 16384, windowBits: window_bits|enable_windows_gzip})
+ @inflating_buffer = ''
+ that = this
+ @inflater_pako.onData = (chunk) ->
+ that.inflating_buffer += chunk
+ return
+ return
+
+ decompress: (chunk, islastchunk) ->
+ @inflating_buffer = ''
+ @inflater_pako.push(chunk, islastchunk)
+ @ended = @inflater_pako.ended
+ @strm = @inflater_pako.strm
+ return @inflating_buffer
+
+class jbfilereadersync
+ constructor: (@file, @gzipped) ->
+ @buffer = ''
+ @filesize = @file.size
+ @chunksize = 1024 * 512
+ @reader = new FileReaderSync()
+
+ if @gzipped
+ @inflater = new _inflater()
+
+ @islastchunk = false
+
+ @fpos = 0
+ @endpos = 0
+
+ @eof = false
+
+ return
+
+ _getchunk: ->
+ if @fpos + @chunksize >= @filesize
+ @endpos = @filesize
+ @islastchunk = true
+ else
+ @endpos = @fpos + @chunksize
+ blob = @file.slice(@fpos, @endpos)
+
+ @fpos += @endpos - @fpos
+ if @gzipped
+ raw_array = new Uint8Array(@reader.readAsArrayBuffer(blob))
+ s = @inflater.decompress(raw_array, @islastchunk)
+ if s
+ if @inflater.ended and (@inflater.strm.avail_in or !@islastchunk)
+ # Non-standard gzip. See http://www.gzip.org/#faq8
+ remaining_bytes = @inflater.strm.avail_in
+ rel_pos = 0
+ while raw_array[raw_array.byteLength-remaining_bytes+rel_pos] == 0
+ rel_pos++
+ @fpos -= remaining_bytes-rel_pos
+ @inflater = new _inflater() # Renew Pako
+ else
+ throw 'Something wrong with the gzipped file!'
+ else
+ s = @reader.readAsText(blob)
+ return s
+
+ readline: () ->
+ if @eof
+ return ""
+
+ lfpos = @buffer.indexOf("\n")
+ while lfpos == -1
+ if @fpos >= @filesize
+ result = @buffer
+ @buffer = ""
+ @fpos = @filesize
+ @eof = true
+ return result
+ @buffer += @_getchunk()
+ lfpos = @buffer.indexOf("\n")
+
+ if @buffer[lfpos-1] == "\r"
+ result = @buffer[...lfpos-1]
+ else
+ result = @buffer[...lfpos]
+ @buffer = @buffer[lfpos+1...]
+ return result
+
+class jbfilereader
+ constructor: (@file, @gzipped) ->
+ @buffer = ''
+ @filesize = @file.size
+ @chunksize = 1024 * 512
+ @reader = new FileReader()
+
+ if @gzipped
+ @inflater = new _inflater()
+
+ @islastchunk = false
+
+ @fpos = 0
+ @endpos = 0
+
+ @eof = false
+
+ return
+
+ _readblob: (blob) ->
+ that = this
+ readpromise = new Promise( (resolve, reject) ->
+ that.reader.onload = (e) ->
+ resolve(e.target.result)
+ that.reader.onerror = ->
+ reject()
+ return
+ )
+ if @gzipped
+ @reader.readAsArrayBuffer(blob)
+ else
+ @reader.readAsText(blob)
+ return readpromise
+
+ _getchunk: ->
+ if @fpos + @chunksize >= @filesize
+ @endpos = @filesize
+ @islastchunk = true
+ else
+ @endpos = @fpos + @chunksize
+ blob = @file.slice(@fpos, @endpos)
+
+ that = this
+ chunkpromise = new Promise( (resolve, reject) ->
+ readpromise = that._readblob(blob)
+ readpromise.then( (s) ->
+ that.fpos += that.endpos - that.fpos
+ if that.gzipped
+ raw_array = new Uint8Array(s)
+ s = that.inflater.decompress(raw_array, that.islastchunk)
+ if s
+ if that.inflater.ended and (that.inflater.strm.avail_in or !that.islastchunk)
+ # Non-standard gzip. See http://www.gzip.org/#faq8
+ remaining_bytes = that.inflater.strm.avail_in
+ rel_pos = 0
+ while raw_array[raw_array.byteLength-remaining_bytes+rel_pos] == 0
+ rel_pos++
+ that.fpos -= remaining_bytes-rel_pos
+ that.inflater = new _inflater() # Renew Pako
+ else
+ alert('Something wrong with the gzipped file!')
+ reject()
+ that.buffer += s
+ resolve()
+ return
+ ).catch( (s) ->
+ alert('Something wrong while reading file!')
+ reject()
+ return
+ )
+ )
+ return chunkpromise
+
+ readline: (callback) ->
+ if @eof
+ callback("")
+
+ lfpos = @buffer.indexOf("\n")
+ if lfpos == -1
+ if @fpos >= @filesize
+ result = @buffer
+ @buffer = ""
+ @eof = true
+ callback(result)
+ else
+ that = this
+ datapromise = @_getchunk()
+ datapromise.then( -> that.readline(callback) )
+ else
+ if @buffer[lfpos] == "\r"
+ result = @buffer[...lfpos-1]
+ else
+ result = @buffer[...lfpos]
+ @buffer = @buffer[lfpos+1...]
+ callback(result)
+ return
diff --git a/core/jbfilereader.js b/core/jbfilereader.js
new file mode 100644
index 0000000..b4fe680
--- /dev/null
+++ b/core/jbfilereader.js
@@ -0,0 +1,251 @@
+// Generated by CoffeeScript 1.8.0
+
+/*
+jbfilereader.coffee
+
+Copyright (c) 2015 Jeongbin Park
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+ */
+var jbfilereader, jbfilereadersync, _inflater;
+
+_inflater = (function() {
+ function _inflater() {
+ var enable_windows_gzip, that, window_bits;
+ window_bits = 15;
+ enable_windows_gzip = 32;
+ this.inflater_pako = new pako.Inflate({
+ to: 'string',
+ chunkSize: 16384,
+ windowBits: window_bits | enable_windows_gzip
+ });
+ this.inflating_buffer = '';
+ that = this;
+ this.inflater_pako.onData = function(chunk) {
+ that.inflating_buffer += chunk;
+ };
+ return;
+ }
+
+ _inflater.prototype.decompress = function(chunk, islastchunk) {
+ this.inflating_buffer = '';
+ this.inflater_pako.push(chunk, islastchunk);
+ this.ended = this.inflater_pako.ended;
+ this.strm = this.inflater_pako.strm;
+ return this.inflating_buffer;
+ };
+
+ return _inflater;
+
+})();
+
+jbfilereadersync = (function() {
+ function jbfilereadersync(file, gzipped) {
+ this.file = file;
+ this.gzipped = gzipped;
+ this.buffer = '';
+ this.filesize = this.file.size;
+ this.chunksize = 1024 * 512;
+ this.reader = new FileReaderSync();
+ if (this.gzipped) {
+ this.inflater = new _inflater();
+ }
+ this.islastchunk = false;
+ this.fpos = 0;
+ this.endpos = 0;
+ this.eof = false;
+ return;
+ }
+
+ jbfilereadersync.prototype._getchunk = function() {
+ var blob, raw_array, rel_pos, remaining_bytes, s;
+ if (this.fpos + this.chunksize >= this.filesize) {
+ this.endpos = this.filesize;
+ this.islastchunk = true;
+ } else {
+ this.endpos = this.fpos + this.chunksize;
+ }
+ blob = this.file.slice(this.fpos, this.endpos);
+ this.fpos += this.endpos - this.fpos;
+ if (this.gzipped) {
+ raw_array = new Uint8Array(this.reader.readAsArrayBuffer(blob));
+ s = this.inflater.decompress(raw_array, this.islastchunk);
+ if (s) {
+ if (this.inflater.ended && (this.inflater.strm.avail_in || !this.islastchunk)) {
+ remaining_bytes = this.inflater.strm.avail_in;
+ rel_pos = 0;
+ while (raw_array[raw_array.byteLength - remaining_bytes + rel_pos] === 0) {
+ rel_pos++;
+ }
+ this.fpos -= remaining_bytes - rel_pos;
+ this.inflater = new _inflater();
+ }
+ } else {
+ throw 'Something wrong with the gzipped file!';
+ }
+ } else {
+ s = this.reader.readAsText(blob);
+ }
+ return s;
+ };
+
+ jbfilereadersync.prototype.readline = function() {
+ var lfpos, result;
+ if (this.eof) {
+ return "";
+ }
+ lfpos = this.buffer.indexOf("\n");
+ while (lfpos === -1) {
+ if (this.fpos >= this.filesize) {
+ result = this.buffer;
+ this.buffer = "";
+ this.fpos = this.filesize;
+ this.eof = true;
+ return result;
+ }
+ this.buffer += this._getchunk();
+ lfpos = this.buffer.indexOf("\n");
+ }
+ if (this.buffer[lfpos - 1] === "\r") {
+ result = this.buffer.slice(0, lfpos - 1);
+ } else {
+ result = this.buffer.slice(0, lfpos);
+ }
+ this.buffer = this.buffer.slice(lfpos + 1);
+ return result;
+ };
+
+ return jbfilereadersync;
+
+})();
+
+jbfilereader = (function() {
+ function jbfilereader(file, gzipped) {
+ this.file = file;
+ this.gzipped = gzipped;
+ this.buffer = '';
+ this.filesize = this.file.size;
+ this.chunksize = 1024 * 512;
+ this.reader = new FileReader();
+ if (this.gzipped) {
+ this.inflater = new _inflater();
+ }
+ this.islastchunk = false;
+ this.fpos = 0;
+ this.endpos = 0;
+ this.eof = false;
+ return;
+ }
+
+ jbfilereader.prototype._readblob = function(blob) {
+ var readpromise, that;
+ that = this;
+ readpromise = new Promise(function(resolve, reject) {
+ that.reader.onload = function(e) {
+ return resolve(e.target.result);
+ };
+ that.reader.onerror = function() {
+ return reject();
+ };
+ });
+ if (this.gzipped) {
+ this.reader.readAsArrayBuffer(blob);
+ } else {
+ this.reader.readAsText(blob);
+ }
+ return readpromise;
+ };
+
+ jbfilereader.prototype._getchunk = function() {
+ var blob, chunkpromise, that;
+ if (this.fpos + this.chunksize >= this.filesize) {
+ this.endpos = this.filesize;
+ this.islastchunk = true;
+ } else {
+ this.endpos = this.fpos + this.chunksize;
+ }
+ blob = this.file.slice(this.fpos, this.endpos);
+ that = this;
+ chunkpromise = new Promise(function(resolve, reject) {
+ var readpromise;
+ readpromise = that._readblob(blob);
+ return readpromise.then(function(s) {
+ var raw_array, rel_pos, remaining_bytes;
+ that.fpos += that.endpos - that.fpos;
+ if (that.gzipped) {
+ raw_array = new Uint8Array(s);
+ s = that.inflater.decompress(raw_array, that.islastchunk);
+ if (s) {
+ if (that.inflater.ended && (that.inflater.strm.avail_in || !that.islastchunk)) {
+ remaining_bytes = that.inflater.strm.avail_in;
+ rel_pos = 0;
+ while (raw_array[raw_array.byteLength - remaining_bytes + rel_pos] === 0) {
+ rel_pos++;
+ }
+ that.fpos -= remaining_bytes - rel_pos;
+ that.inflater = new _inflater();
+ }
+ } else {
+ alert('Something wrong with the gzipped file!');
+ reject();
+ }
+ }
+ that.buffer += s;
+ resolve();
+ })["catch"](function(s) {
+ alert('Something wrong while reading file!');
+ reject();
+ });
+ });
+ return chunkpromise;
+ };
+
+ jbfilereader.prototype.readline = function(callback) {
+ var datapromise, lfpos, result, that;
+ if (this.eof) {
+ callback("");
+ }
+ lfpos = this.buffer.indexOf("\n");
+ if (lfpos === -1) {
+ if (this.fpos >= this.filesize) {
+ result = this.buffer;
+ this.buffer = "";
+ this.eof = true;
+ callback(result);
+ } else {
+ that = this;
+ datapromise = this._getchunk();
+ datapromise.then(function() {
+ return that.readline(callback);
+ });
+ }
+ } else {
+ if (this.buffer[lfpos] === "\r") {
+ result = this.buffer.slice(0, lfpos - 1);
+ } else {
+ result = this.buffer.slice(0, lfpos);
+ }
+ this.buffer = this.buffer.slice(lfpos + 1);
+ callback(result);
+ }
+ };
+
+ return jbfilereader;
+
+})();
diff --git a/core/miseq-analyzer.coffee b/core/miseq-analyzer.coffee
new file mode 100644
index 0000000..6074a33
--- /dev/null
+++ b/core/miseq-analyzer.coffee
@@ -0,0 +1,290 @@
+###
+cas-analyser.coffee
+
+Copyright (c) 2015 Jeongbin Park
+
+GNU General Public License
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+
+###
+
+pri_len = 15 # Constant
+s_seq = ''
+seq_range = ''
+
+joins_length = 0
+seq_count = {}
+
+pri_for_patterns = []
+pri_back_patterns = []
+
+set_primer_patterns = (_pri_for_patterns, _pri_back_patterns) ->
+ pri_for_patterns = _pri_for_patterns
+ pri_back_patterns = _pri_back_patterns
+
+empty_cache = ->
+ joins_length = 0
+ seq_count = {}
+ return
+
+process_chunk = (seqs) ->
+ for seq in seqs
+ flag_for = 0
+ flag_back = 0
+
+ for pattern in pri_for_patterns
+ pattern = new RegExp(pattern)
+ m = pattern.exec(seq)
+ if m
+ start_pos = m.index
+ flag_for = 1
+
+ for pattern in pri_back_patterns
+ pattern = new RegExp(pattern)
+ m = pattern.exec(seq)
+ if m
+ end_pos = m.index
+ flag_back = 1
+
+ if flag_for and flag_back
+ cut_seq = seq[start_pos...(end_pos+pri_len)]
+ if cut_seq of seq_count
+ seq_count[cut_seq] += 1
+ else
+ seq_count[cut_seq] = 1
+ joins_length += 1
+ return
+
+parse_file = (file, pgcallback, chunkcallback) ->
+ seq_list = []
+ bufsize = 10000
+ gzipped = 0
+ if file.name.split('.').pop() == 'gz'
+ gzipped = 1
+ f = new jbfilereadersync(file, gzipped)
+
+ linecnt = 0
+ line = f.readline()
+ while line.length > 0
+ if linecnt %% 4 == 1
+ seq_list.push(line)
+ if seq_list.length == bufsize
+ chunkcallback(seq_list)
+ seq_list = []
+ if linecnt %% 1000 == 0
+ pgcallback(f.fpos*100/f.filesize)
+ line = f.readline()
+ linecnt += 1
+ if seq_list.length > 0
+ chunkcallback(seq_list)
+ pgcallback(f.fpos*100/f.filesize)
+ return
+
+revcompstr = (s) ->
+ l = s.split('').reverse()
+ for i in [0...l.length] by 1
+ if l[i] == 'A'
+ l[i] = 'T'
+ else if l[i] == 'T'
+ l[i] = 'A'
+ else if l[i] == 'G'
+ l[i] = 'C'
+ else if l[i] == 'C'
+ l[i] = 'G'
+ else if l[i] == 'a'
+ l[i] = 't'
+ else if l[i] == 't'
+ l[i] = 'a'
+ else if l[i] == 'g'
+ l[i] = 'c'
+ else if l[i] == 'c'
+ l[i] = 'g'
+ return l.join('')
+
+run_cas_analyser = (seq_range, seq_hdr, filt_n, filt_r, pgcallback)->
+ tot_results = []
+ mut_results = []
+ count_seqs = []
+ totlr_count = 0
+ tot_count = 0
+
+ length_range = seq_range.length
+
+ n = Object.keys(seq_count).length//20
+ i = 0
+ for seq of seq_count
+ if !seq_count.hasOwnProperty(seq)
+ continue
+ item_cnt = seq_count[seq]
+ totlr_count += item_cnt
+ if item_cnt > filt_n
+ count_seqs.push( {"seq": seq, "count": item_cnt} )
+ tot_count += item_cnt
+ if i % n == 0
+ pgcallback(i/Object.keys(seq_count).length*50)
+ i += 1
+ pgcallback(50)
+
+ query_cnt = 0
+
+ compare = (a, b) ->
+ if (a.count < b.count)
+ return 1
+ if (a.count > b.count)
+ return -1
+ return 0
+
+ count_seqs.sort(compare)
+
+ data = {table: [], il: [], dl: [], is: [], ds: [], hdr: 0}
+ cnt_hdr = 0
+ cnt_ins = 0
+ cnt_del = 0
+
+ dscnt = 1
+ iscnt = 1
+
+ re_gap = /-+/g
+
+ for i in [0..seq_range.length] by 1
+ data.il.push( [i, 0] )
+ data.dl.push( [i, 0] )
+
+ n = count_seqs.length // 20
+ for i in [0...count_seqs.length] by 1
+ entry = []
+ p = needle(seq_range, count_seqs[i].seq, 10, 0.5, 10, 0.5)
+ entry[0] = i + 1
+ entry[1] = p[0]
+ entry[2] = p[2]
+ entry[3] = p[1]
+ entry[4] = count_seqs[i].seq.length
+ entry[5] = count_seqs[i].count
+ if seq_range.length == entry[4]
+ entry[6] = 0 # WT
+ else
+ if filt_r > 0 and s_seq != '' and count_seqs[i].seq.indexOf(s_seq) > 0
+ entry[6] = 0
+ else
+ if entry[4] > seq_range.length
+ entry[6] = 1 # Insertion
+ cnt_ins += entry[5]
+ else
+ entry[6] = 2 # Deletion
+ cnt_del += entry[5]
+ if seq_hdr == ''
+ entry[7] = -2
+ else
+ entry[7] = count_seqs[i].seq.indexOf(seq_hdr)
+ if entry[7] > 0
+ cnt_hdr += entry[5]
+
+ data.table.push(entry)
+
+ cpos = 0
+ if entry[6] == 1
+ loop
+ m = re_gap.exec(entry[1])
+ if m
+ gap = m[0]
+ if data.is.length < gap.length
+ for j in [0..gap.length - data.is.length] by 1
+ data.is.push([iscnt++, 0])
+ data.is[gap.length-1][1] += count_seqs[i].count
+ else
+ break
+ for j in [0..entry[1].length - 1] by 1
+ if entry[1][j] != '-'
+ cpos += 1
+ if cpos >= seq_range.length
+ break
+ if entry[1][j+1] == '-'
+ data.il[cpos][1] += count_seqs[i].count
+ else if entry[6] == 2
+ loop
+ m = re_gap.exec(entry[2])
+ if m
+ gap = m[0]
+ if data.ds.length < gap.length
+ for j in [0..gap.length - data.ds.length] by 1
+ data.ds.push([dscnt++, 0])
+ data.ds[gap.length-1][1] += count_seqs[i].count
+ else
+ break
+ for j in [0..entry[1].length] by 1
+ if entry[2][j] == '-'
+ data.dl[cpos][1] += count_seqs[i].count
+ if entry[1][j] != '-'
+ cpos += 1
+ if i % n == 0
+ pgcallback(50+50*i/(count_seqs.length-1))
+
+ for i in [0..seq_range.length] by 1
+ data.il[i][1] /= tot_count
+ data.dl[i][1] /= tot_count
+ data.il[i][1] *= 100
+ data.dl[i][1] *= 100
+
+ data.hdr = cnt_hdr
+ data.joins_length = joins_length
+ data.totlr_count = totlr_count
+ data.tot_count = tot_count
+ data.cnt_ins = cnt_ins
+ data.cnt_del = cnt_del
+
+ pgcallback(100)
+
+ return data
+
+parse_joined = ->
+ reader = new FileReader()
+ chunksize = 1024*1024*10
+ noncomplete_line = ''
+ fpos = 0
+ fstep = 200
+ nline = 0
+ feof = 0
+
+ getchunk = ->
+ if fpos >= joinedfile.size
+ feof = 1
+ readline()
+
+ if fpos + chunksize >= joinedfile.size
+ endpos = joinedfile.size
+ else
+ endpos = fpos + chunksize
+
+ blob = joinedfile.slice(fpos, endpos)
+ fpos += endpos - fpos
+ reader.readAsText(blob)
+
+ reader.onload = ->
+ chunk_lines = reader.result.replace(/\r\n|\n\r|\r/, '\n').split('\n')
+ chunk_lines[0] = noncomplete_line + chunk_lines[0]
+ noncomplete_line = chunk_lines[chunk_lines.length-1]
+ chunk_lines = chunk_lines[...chunk_lines.length-1]
+ readline()
+
+ readline = ->
+ if nline >= chunk_lines.length
+ if feof
+ return ''
+ else
+ getchunk()
+ return
+ return chunk_lines[nline++]
+
+ line = readline()
diff --git a/core/miseq-analyzer.js b/core/miseq-analyzer.js
new file mode 100644
index 0000000..caf0f00
--- /dev/null
+++ b/core/miseq-analyzer.js
@@ -0,0 +1,349 @@
+// Generated by CoffeeScript 1.8.0
+
+/*
+cas-analyser.coffee
+
+Copyright (c) 2015 Jeongbin Park
+
+GNU General Public License
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+ */
+var empty_cache, joins_length, parse_file, parse_joined, pri_back_patterns, pri_for_patterns, pri_len, process_chunk, revcompstr, run_cas_analyser, s_seq, seq_count, seq_range, set_primer_patterns,
+ __modulo = function(a, b) { return (+a % (b = +b) + b) % b; };
+
+pri_len = 15;
+
+s_seq = '';
+
+seq_range = '';
+
+joins_length = 0;
+
+seq_count = {};
+
+pri_for_patterns = [];
+
+pri_back_patterns = [];
+
+set_primer_patterns = function(_pri_for_patterns, _pri_back_patterns) {
+ pri_for_patterns = _pri_for_patterns;
+ return pri_back_patterns = _pri_back_patterns;
+};
+
+empty_cache = function() {
+ joins_length = 0;
+ seq_count = {};
+};
+
+process_chunk = function(seqs) {
+ var cut_seq, end_pos, flag_back, flag_for, m, pattern, seq, start_pos, _i, _j, _k, _len, _len1, _len2;
+ for (_i = 0, _len = seqs.length; _i < _len; _i++) {
+ seq = seqs[_i];
+ flag_for = 0;
+ flag_back = 0;
+ for (_j = 0, _len1 = pri_for_patterns.length; _j < _len1; _j++) {
+ pattern = pri_for_patterns[_j];
+ pattern = new RegExp(pattern);
+ m = pattern.exec(seq);
+ if (m) {
+ start_pos = m.index;
+ flag_for = 1;
+ }
+ }
+ for (_k = 0, _len2 = pri_back_patterns.length; _k < _len2; _k++) {
+ pattern = pri_back_patterns[_k];
+ pattern = new RegExp(pattern);
+ m = pattern.exec(seq);
+ if (m) {
+ end_pos = m.index;
+ flag_back = 1;
+ }
+ }
+ if (flag_for && flag_back) {
+ cut_seq = seq.slice(start_pos, end_pos + pri_len);
+ if (cut_seq in seq_count) {
+ seq_count[cut_seq] += 1;
+ } else {
+ seq_count[cut_seq] = 1;
+ }
+ }
+ joins_length += 1;
+ }
+};
+
+parse_file = function(file, pgcallback, chunkcallback) {
+ var bufsize, f, gzipped, line, linecnt, seq_list;
+ seq_list = [];
+ bufsize = 10000;
+ gzipped = 0;
+ if (file.name.split('.').pop() === 'gz') {
+ gzipped = 1;
+ }
+ f = new jbfilereadersync(file, gzipped);
+ linecnt = 0;
+ line = f.readline();
+ while (line.length > 0) {
+ if (__modulo(linecnt, 4) === 1) {
+ seq_list.push(line);
+ if (seq_list.length === bufsize) {
+ chunkcallback(seq_list);
+ seq_list = [];
+ }
+ }
+ if (__modulo(linecnt, 1000) === 0) {
+ pgcallback(f.fpos * 100 / f.filesize);
+ }
+ line = f.readline();
+ linecnt += 1;
+ }
+ if (seq_list.length > 0) {
+ chunkcallback(seq_list);
+ pgcallback(f.fpos * 100 / f.filesize);
+ }
+};
+
+revcompstr = function(s) {
+ var i, l, _i, _ref;
+ l = s.split('').reverse();
+ for (i = _i = 0, _ref = l.length; _i < _ref; i = _i += 1) {
+ if (l[i] === 'A') {
+ l[i] = 'T';
+ } else if (l[i] === 'T') {
+ l[i] = 'A';
+ } else if (l[i] === 'G') {
+ l[i] = 'C';
+ } else if (l[i] === 'C') {
+ l[i] = 'G';
+ } else if (l[i] === 'a') {
+ l[i] = 't';
+ } else if (l[i] === 't') {
+ l[i] = 'a';
+ } else if (l[i] === 'g') {
+ l[i] = 'c';
+ } else if (l[i] === 'c') {
+ l[i] = 'g';
+ }
+ }
+ return l.join('');
+};
+
+run_cas_analyser = function(seq_range, seq_hdr, filt_n, filt_r, pgcallback) {
+ var cnt_del, cnt_hdr, cnt_ins, compare, count_seqs, cpos, data, dscnt, entry, gap, i, iscnt, item_cnt, j, length_range, m, mut_results, n, p, query_cnt, re_gap, seq, tot_count, tot_results, totlr_count, _i, _j, _k, _l, _m, _n, _o, _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6;
+ tot_results = [];
+ mut_results = [];
+ count_seqs = [];
+ totlr_count = 0;
+ tot_count = 0;
+ length_range = seq_range.length;
+ n = Math.floor(Object.keys(seq_count).length / 20);
+ i = 0;
+ for (seq in seq_count) {
+ if (!seq_count.hasOwnProperty(seq)) {
+ continue;
+ }
+ item_cnt = seq_count[seq];
+ totlr_count += item_cnt;
+ if (item_cnt > filt_n) {
+ count_seqs.push({
+ "seq": seq,
+ "count": item_cnt
+ });
+ tot_count += item_cnt;
+ }
+ if (i % n === 0) {
+ pgcallback(i / Object.keys(seq_count).length * 50);
+ }
+ i += 1;
+ }
+ pgcallback(50);
+ query_cnt = 0;
+ compare = function(a, b) {
+ if (a.count < b.count) {
+ return 1;
+ }
+ if (a.count > b.count) {
+ return -1;
+ }
+ return 0;
+ };
+ count_seqs.sort(compare);
+ data = {
+ table: [],
+ il: [],
+ dl: [],
+ is: [],
+ ds: [],
+ hdr: 0
+ };
+ cnt_hdr = 0;
+ cnt_ins = 0;
+ cnt_del = 0;
+ dscnt = 1;
+ iscnt = 1;
+ re_gap = /-+/g;
+ for (i = _i = 0, _ref = seq_range.length; _i <= _ref; i = _i += 1) {
+ data.il.push([i, 0]);
+ data.dl.push([i, 0]);
+ }
+ n = Math.floor(count_seqs.length / 20);
+ for (i = _j = 0, _ref1 = count_seqs.length; _j < _ref1; i = _j += 1) {
+ entry = [];
+ p = needle(seq_range, count_seqs[i].seq, 10, 0.5, 10, 0.5);
+ entry[0] = i + 1;
+ entry[1] = p[0];
+ entry[2] = p[2];
+ entry[3] = p[1];
+ entry[4] = count_seqs[i].seq.length;
+ entry[5] = count_seqs[i].count;
+ if (seq_range.length === entry[4]) {
+ entry[6] = 0;
+ } else {
+ if (filt_r > 0 && s_seq !== '' && count_seqs[i].seq.indexOf(s_seq) > 0) {
+ entry[6] = 0;
+ } else {
+ if (entry[4] > seq_range.length) {
+ entry[6] = 1;
+ cnt_ins += entry[5];
+ } else {
+ entry[6] = 2;
+ cnt_del += entry[5];
+ }
+ }
+ }
+ if (seq_hdr === '') {
+ entry[7] = -2;
+ } else {
+ entry[7] = count_seqs[i].seq.indexOf(seq_hdr);
+ if (entry[7] > 0) {
+ cnt_hdr += entry[5];
+ }
+ }
+ data.table.push(entry);
+ cpos = 0;
+ if (entry[6] === 1) {
+ while (true) {
+ m = re_gap.exec(entry[1]);
+ if (m) {
+ gap = m[0];
+ if (data.is.length < gap.length) {
+ for (j = _k = 0, _ref2 = gap.length - data.is.length; _k <= _ref2; j = _k += 1) {
+ data.is.push([iscnt++, 0]);
+ }
+ }
+ data.is[gap.length - 1][1] += count_seqs[i].count;
+ } else {
+ break;
+ }
+ }
+ for (j = _l = 0, _ref3 = entry[1].length - 1; _l <= _ref3; j = _l += 1) {
+ if (entry[1][j] !== '-') {
+ cpos += 1;
+ if (cpos >= seq_range.length) {
+ break;
+ }
+ if (entry[1][j + 1] === '-') {
+ data.il[cpos][1] += count_seqs[i].count;
+ }
+ }
+ }
+ } else if (entry[6] === 2) {
+ while (true) {
+ m = re_gap.exec(entry[2]);
+ if (m) {
+ gap = m[0];
+ if (data.ds.length < gap.length) {
+ for (j = _m = 0, _ref4 = gap.length - data.ds.length; _m <= _ref4; j = _m += 1) {
+ data.ds.push([dscnt++, 0]);
+ }
+ }
+ data.ds[gap.length - 1][1] += count_seqs[i].count;
+ } else {
+ break;
+ }
+ }
+ for (j = _n = 0, _ref5 = entry[1].length; _n <= _ref5; j = _n += 1) {
+ if (entry[2][j] === '-') {
+ data.dl[cpos][1] += count_seqs[i].count;
+ }
+ if (entry[1][j] !== '-') {
+ cpos += 1;
+ }
+ }
+ }
+ if (i % n === 0) {
+ pgcallback(50 + 50 * i / (count_seqs.length - 1));
+ }
+ }
+ for (i = _o = 0, _ref6 = seq_range.length; _o <= _ref6; i = _o += 1) {
+ data.il[i][1] /= tot_count;
+ data.dl[i][1] /= tot_count;
+ data.il[i][1] *= 100;
+ data.dl[i][1] *= 100;
+ }
+ data.hdr = cnt_hdr;
+ data.joins_length = joins_length;
+ data.totlr_count = totlr_count;
+ data.tot_count = tot_count;
+ data.cnt_ins = cnt_ins;
+ data.cnt_del = cnt_del;
+ pgcallback(100);
+ return data;
+};
+
+parse_joined = function() {
+ var chunksize, feof, fpos, fstep, getchunk, line, nline, noncomplete_line, reader, readline;
+ reader = new FileReader();
+ chunksize = 1024 * 1024 * 10;
+ noncomplete_line = '';
+ fpos = 0;
+ fstep = 200;
+ nline = 0;
+ feof = 0;
+ getchunk = function() {
+ var blob, endpos;
+ if (fpos >= joinedfile.size) {
+ feof = 1;
+ readline();
+ }
+ if (fpos + chunksize >= joinedfile.size) {
+ endpos = joinedfile.size;
+ } else {
+ endpos = fpos + chunksize;
+ }
+ blob = joinedfile.slice(fpos, endpos);
+ fpos += endpos - fpos;
+ return reader.readAsText(blob);
+ };
+ reader.onload = function() {
+ var chunk_lines;
+ chunk_lines = reader.result.replace(/\r\n|\n\r|\r/, '\n').split('\n');
+ chunk_lines[0] = noncomplete_line + chunk_lines[0];
+ noncomplete_line = chunk_lines[chunk_lines.length - 1];
+ chunk_lines = chunk_lines.slice(0, chunk_lines.length - 1);
+ return readline();
+ };
+ readline = function() {
+ if (nline >= chunk_lines.length) {
+ if (feof) {
+ return '';
+ } else {
+ getchunk();
+ return;
+ }
+ }
+ return chunk_lines[nline++];
+ };
+ return line = readline();
+};
diff --git a/core/needle.js b/core/needle.js
new file mode 100644
index 0000000..3274869
--- /dev/null
+++ b/core/needle.js
@@ -0,0 +1,291 @@
+/*
+ * needle.js
+ *
+ * Author: Jeongbin Park (pjb7687 at gmail.com)
+ * Based on source code of 'needle' in EMBOSS software suite (http://emboss.sourceforge.net/).
+ *
+ * GNU General Public License
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+ function needle(a, b, gapopen, gapextend, endgapopen, endgapextend) {
+ function E_FPEQ(a, b, e) { return (((b - e) < a) && (a < (b + e))); }
+
+ var sub = [[5, -4, -4, -4, -4, 1, 1, -4, -4, 1, -4, -1, -1, -1, -2, -4], [-4, 5, -4, -4, -4, 1, -4, 1, 1, -4, -1, -4, -1, -1, -2, 5], [-4, -4, 5, -4, 1, -4, 1, -4, 1, -4, -1, -1, -4, -1, -2, -4], [-4, -4, -4, 5, 1, -4, -4, 1, -4, 1, -1, -1, -1, -4, -2, -4], [-4, -4, 1, 1, -1, -4, -2, -2, -2, -2, -1, -1, -3, -3, -1, -4], [1, 1, -4, -4, -4, -1, -2, -2, -2, -2, -3, -3, -1, -1, -1, 1], [1, -4, 1, -4, -2, -2, -1, -4, -2, -2, -3, -1, -3, -1, -1, -4], [-4, 1, -4, 1, -2, -2, -4, -1, -2, -2, -1, -3, -1, -3, -1, 1], [-4, 1, 1, -4, -2, -2, -2, -2, -1, -4, -1, -3, -3, -1, -1, 1], [1, -4, -4, 1, -2, -2, -2, -2, -4, -1, -3, -1, -1, -3, -1, -4], [-4, -1, -1, -1, -1, -3, -3, -1, -1, -3, -1, -2, -2, -2, -1, -1], [-1, -4, -1, -1, -1, -3, -1, -3, -3, -1, -2, -1, -2, -2, -1, -4], [-1, -1, -4, -1, -3, -1, -3, -1, -3, -1, -2, -2, -1, -2, -1, -1], [-1, -1, -1, -4, -3, -1, -1, -3, -1, -3, -2, -2, -2, -1, -1, -1], [-2, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2], [-4, 5, -4, -4, -4, 1, -4, 1, 1, -4, -1, -4, -1, -1, -2, 5]]; // EDNAFULL
+ var base_to_idx = {'A': 0, 'C': 3, 'B': 10, 'D': 13, 'G': 2, 'H': 12, 'K': 8, 'M': 9, 'N': 14, 'S': 4, 'R': 6, 'U': 15, 'T': 1, 'W': 5, 'V': 11, 'Y': 7}; // for EDNAFULL
+ var idx_to_base = {0: 'A', 1: 'T', 2: 'G', 3: 'C', 4: 'S', 5: 'W', 6: 'R', 7: 'Y', 8: 'K', 9: 'M', 10: 'B', 11: 'V', 12: 'H', 13: 'D', 14: 'N', 15: 'U'}; // for EDNAFULL
+
+ var ix = [], iy = [], m = [];
+ var ixp, iyp, mp;
+
+ var compass = [];
+
+ var i, j;
+ var cursor, cursorp;
+
+ var p = []; q = [];
+
+ for(i=0; i= testeg)
+ iy[cursor] = testog;
+ else
+ iy[cursor] = testeg;
+ m[cursor] = match - (endgapopen + (ypos - 1) * endgapextend);
+ ix[cursor] = -endgapopen - ypos * endgapextend - gapopen;
+ }
+ ix[cursor] -= endgapopen;
+ ix[cursor] += gapopen;
+
+ cursor = 0;
+
+ for (xpos=1; xpos= testeg)
+ ix[cursor] = testog;
+ else
+ ix[cursor] = testeg;
+
+ m[cursor] = match - (endgapopen + (xpos - 1) * endgapextend);
+ iy[cursor] = -endgapopen - xpos * endgapextend - gapopen;
+ }
+ iy[cursor] -= endgapopen;
+ iy[cursor] += gapopen;
+
+ xpos = 1;
+ while (xpos != lenb) {
+ ypos = 1;
+ bconvcode = q[xpos];
+
+ cursorp = xpos-1;
+ cursor = xpos++;
+
+ while (ypos < lena) {
+ match = sub[p[ypos++]][bconvcode];
+ cursor += lenb;
+
+ mp = m[cursorp];
+ ixp = ix[cursorp];
+ iyp = iy[cursorp];
+
+ if (mp > ixp && mp > iyp)
+ m[cursor] = mp + match;
+ else if (ixp > iyp)
+ m[cursor] = ixp + match;
+ else
+ m[cursor] = iyp + match;
+
+ cursorp += 1;
+ if (xpos == lenb) {
+ testog = m[cursorp] - endgapopen;
+ testeg = iy[cursorp] - endgapextend;
+ } else {
+ testog = m[cursorp];
+ if (testog < ix[cursorp])
+ testog = ix[cursorp];
+
+ testog -= gapopen;
+ testeg = iy[cursorp] - gapextend;
+ }
+ if (testog > testeg)
+ iy[cursor] = testog;
+ else
+ iy[cursor] = testeg;
+
+ cursorp += lenb;
+
+ cursorp -= 1;
+ if (ypos == lena) {
+ testog = m[cursorp] - endgapopen;
+ testeg= ix[cursorp] - endgapextend;
+ } else {
+ testog = m[cursorp];
+ if (testog < iy[cursorp])
+ testog = iy[cursorp];
+ testog -= gapopen;
+ testeg = ix[cursorp] - gapextend;
+ }
+ if (testog > testeg)
+ ix[cursor] = testog;
+ else
+ ix[cursor] = testeg;
+ }
+ }
+
+ score = -32767; // INT_MIN
+ start1 = lena - 1;
+ start2 = lenb - 1;
+
+ cursor = lena * lenb - 1;
+ if (m[cursor] > ix[cursor] && m[cursor] > iy[cursor])
+ score = m[cursor];
+ else if (ix[cursor] > iy[cursor])
+ score = ix[cursor];
+ else
+ score = iy[cursor];
+
+ cursorp = 0;
+ cursor = 1;
+
+ eps = 1.192e-6;
+
+ ypos = start1;
+ xpos = start2;
+
+ while (xpos>=0 && ypos>=0) {
+ cursor = ypos*lenb+xpos;
+ mp = m[cursor];
+
+ if(cursorp == 1 && E_FPEQ((ypos==0||(ypos==lena-1)?endgapextend:gapextend), (ix[cursor]-ix[cursor+1]), eps))
+ {
+ compass[cursor] = 1;
+ xpos--;
+ }
+ else if(cursorp== 2 && E_FPEQ((xpos==0||(xpos==lenb-1)?endgapextend:gapextend), (iy[cursor]-iy[cursor+lenb]), eps))
+ {
+ compass[cursor] = 2;
+ ypos--;
+ }
+ else if(mp >= ix[cursor] && mp>= iy[cursor])
+ {
+
+ if(cursorp == 1 && E_FPEQ(mp,ix[cursor],eps))
+ {
+ compass[cursor] = 1;
+ xpos--;
+ }
+ else if(cursorp == 2 && E_FPEQ(mp,iy[cursor],eps))
+ {
+ compass[cursor] = 2;
+ ypos--;
+ }
+ else
+ {
+ compass[cursor] = 0;
+ ypos--;
+ xpos--;
+ }
+
+ }
+ else if(ix[cursor]>=iy[cursor] && xpos>-1)
+ {
+ compass[cursor] = 1;
+ xpos--;
+ }
+ else if(ypos>-1)
+ {
+ compass[cursor] = 2;
+ ypos--;
+ }
+ else
+ {
+ alert("Needle: Something is seriously wrong in the traceback algorithm");
+ return -1;
+ }
+ cursorp = compass[cursor];
+ }
+
+ for (i=lenb-1; i>start2;) {
+ aln_b.push(idx_to_base[q[i--]]);
+ aln_a.push('-');
+ aln_r.push(' ');
+ }
+ for (j=lena-1; j>start1;) {
+ aln_a.push(idx_to_base[p[j--]]);
+ aln_b.push('-');
+ aln_r.push(' ');
+ }
+
+ while (start2 >= 0 && start1 >= 0)
+ {
+ cursor = start1 * lenb + start2;
+ if(!compass[cursor]) /* diagonal */
+ {
+ b1 = p[start1--]; b2 = q[start2--];
+ aln_a.push(idx_to_base[b1]);
+ aln_b.push(idx_to_base[b2]);
+ if (b1 == b2)
+ aln_r.push('|');
+ else
+ aln_r.push('.');
+ continue;
+ }
+ else if(compass[cursor] == 1) /* Left, gap(s) in vertical */
+ {
+ aln_a.push('-');
+ aln_b.push(idx_to_base[q[start2--]]);
+ aln_r.push(' ');
+ continue;
+ }
+ else if(compass[cursor] == 2) /* Down, gap(s) in horizontal */
+ {
+ aln_a.push(idx_to_base[p[start1--]]);
+ aln_b.push('-');
+ aln_r.push(' ');
+ continue;
+ } else {
+ alert("Needle: Walk Error in NW");
+ return -1;
+ }
+ }
+
+ for (;start2>=0;start2--)
+ {
+ aln_b.push(idx_to_base[q[start2]]);
+ aln_a.push('-');
+ aln_r.push(' ');
+ }
+
+ for (;start1>=0;start1--)
+ {
+ aln_a.push(idx_to_base[p[start1]]);
+ aln_b.push('-');
+ aln_r.push(' ');
+ }
+
+ aln_a = aln_a.reverse().join("");
+ aln_b = aln_b.reverse().join("");
+ aln_r = aln_r.reverse().join(""); //.replace(/ /gi, " ");
+
+ return [aln_a, aln_r, aln_b];
+ }
diff --git a/core/pako_inflate.min.js b/core/pako_inflate.min.js
new file mode 100644
index 0000000..58662fb
--- /dev/null
+++ b/core/pako_inflate.min.js
@@ -0,0 +1,2 @@
+/* pako 0.2.5 nodeca/pako */
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.pako=e()}}(function(){return function e(t,i,n){function a(s,o){if(!i[s]){if(!t[s]){var f="function"==typeof require&&require;if(!o&&f)return f(s,!0);if(r)return r(s,!0);throw new Error("Cannot find module '"+s+"'")}var l=i[s]={exports:{}};t[s][0].call(l.exports,function(e){var i=t[s][1][e];return a(i?i:e)},l,l.exports,e,t,i,n)}return i[s].exports}for(var r="function"==typeof require&&require,s=0;s=0&&t.windowBits<16&&(t.windowBits=-t.windowBits,0===t.windowBits&&(t.windowBits=-15)),!(t.windowBits>=0&&t.windowBits<16)||e&&e.windowBits||(t.windowBits+=32),t.windowBits>15&&t.windowBits<48&&0===(15&t.windowBits)&&(t.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new d,this.strm.avail_out=0;var i=r.inflateInit2(this.strm,t.windowBits);if(i!==f.Z_OK)throw new Error(l[i]);this.header=new h,r.inflateGetHeader(this.strm,this.header)};u.prototype.push=function(e,t){var i,n,a,l,d,h=this.strm,u=this.options.chunkSize;if(this.ended)return!1;n=t===~~t?t:t===!0?f.Z_FINISH:f.Z_NO_FLUSH,h.input="string"==typeof e?o.binstring2buf(e):e,h.next_in=0,h.avail_in=h.input.length;do{if(0===h.avail_out&&(h.output=new s.Buf8(u),h.next_out=0,h.avail_out=u),i=r.inflate(h,f.Z_NO_FLUSH),i!==f.Z_STREAM_END&&i!==f.Z_OK)return this.onEnd(i),this.ended=!0,!1;h.next_out&&(0===h.avail_out||i===f.Z_STREAM_END||0===h.avail_in&&n===f.Z_FINISH)&&("string"===this.options.to?(a=o.utf8border(h.output,h.next_out),l=h.next_out-a,d=o.buf2string(h.output,a),h.next_out=l,h.avail_out=u-l,l&&s.arraySet(h.output,h.output,a,l,0),this.onData(d)):this.onData(s.shrinkBuf(h.output,h.next_out)))}while(h.avail_in>0&&i!==f.Z_STREAM_END);return i===f.Z_STREAM_END&&(n=f.Z_FINISH),n===f.Z_FINISH?(i=r.inflateEnd(this.strm),this.onEnd(i),this.ended=!0,i===f.Z_OK):!0},u.prototype.onData=function(e){this.chunks.push(e)},u.prototype.onEnd=function(e){e===f.Z_OK&&(this.result="string"===this.options.to?this.chunks.join(""):s.flattenChunks(this.chunks)),this.chunks=[],this.err=e,this.msg=this.strm.msg},i.Inflate=u,i.inflate=n,i.inflateRaw=a,i.ungzip=n},{"./utils/common":2,"./utils/strings":3,"./zlib/constants":5,"./zlib/gzheader":7,"./zlib/inflate.js":9,"./zlib/messages":11,"./zlib/zstream":12}],2:[function(e,t,i){"use strict";var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;i.assign=function(e){for(var t=Array.prototype.slice.call(arguments,1);t.length;){var i=t.shift();if(i){if("object"!=typeof i)throw new TypeError(i+"must be non-object");for(var n in i)i.hasOwnProperty(n)&&(e[n]=i[n])}}return e},i.shrinkBuf=function(e,t){return e.length===t?e:e.subarray?e.subarray(0,t):(e.length=t,e)};var a={arraySet:function(e,t,i,n,a){if(t.subarray&&e.subarray)return void e.set(t.subarray(i,i+n),a);for(var r=0;n>r;r++)e[a+r]=t[i+r]},flattenChunks:function(e){var t,i,n,a,r,s;for(n=0,t=0,i=e.length;i>t;t++)n+=e[t].length;for(s=new Uint8Array(n),a=0,t=0,i=e.length;i>t;t++)r=e[t],s.set(r,a),a+=r.length;return s}},r={arraySet:function(e,t,i,n,a){for(var r=0;n>r;r++)e[a+r]=t[i+r]},flattenChunks:function(e){return[].concat.apply([],e)}};i.setTyped=function(e){e?(i.Buf8=Uint8Array,i.Buf16=Uint16Array,i.Buf32=Int32Array,i.assign(i,a)):(i.Buf8=Array,i.Buf16=Array,i.Buf32=Array,i.assign(i,r))},i.setTyped(n)},{}],3:[function(e,t,i){"use strict";function n(e,t){if(65537>t&&(e.subarray&&s||!e.subarray&&r))return String.fromCharCode.apply(null,a.shrinkBuf(e,t));for(var i="",n=0;t>n;n++)i+=String.fromCharCode(e[n]);return i}var a=e("./common"),r=!0,s=!0;try{String.fromCharCode.apply(null,[0])}catch(o){r=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(o){s=!1}for(var f=new a.Buf8(256),l=0;256>l;l++)f[l]=l>=252?6:l>=248?5:l>=240?4:l>=224?3:l>=192?2:1;f[254]=f[254]=1,i.string2buf=function(e){var t,i,n,r,s,o=e.length,f=0;for(r=0;o>r;r++)i=e.charCodeAt(r),55296===(64512&i)&&o>r+1&&(n=e.charCodeAt(r+1),56320===(64512&n)&&(i=65536+(i-55296<<10)+(n-56320),r++)),f+=128>i?1:2048>i?2:65536>i?3:4;for(t=new a.Buf8(f),s=0,r=0;f>s;r++)i=e.charCodeAt(r),55296===(64512&i)&&o>r+1&&(n=e.charCodeAt(r+1),56320===(64512&n)&&(i=65536+(i-55296<<10)+(n-56320),r++)),128>i?t[s++]=i:2048>i?(t[s++]=192|i>>>6,t[s++]=128|63&i):65536>i?(t[s++]=224|i>>>12,t[s++]=128|i>>>6&63,t[s++]=128|63&i):(t[s++]=240|i>>>18,t[s++]=128|i>>>12&63,t[s++]=128|i>>>6&63,t[s++]=128|63&i);return t},i.buf2binstring=function(e){return n(e,e.length)},i.binstring2buf=function(e){for(var t=new a.Buf8(e.length),i=0,n=t.length;n>i;i++)t[i]=e.charCodeAt(i);return t},i.buf2string=function(e,t){var i,a,r,s,o=t||e.length,l=new Array(2*o);for(a=0,i=0;o>i;)if(r=e[i++],128>r)l[a++]=r;else if(s=f[r],s>4)l[a++]=65533,i+=s-1;else{for(r&=2===s?31:3===s?15:7;s>1&&o>i;)r=r<<6|63&e[i++],s--;s>1?l[a++]=65533:65536>r?l[a++]=r:(r-=65536,l[a++]=55296|r>>10&1023,l[a++]=56320|1023&r)}return n(l,a)},i.utf8border=function(e,t){var i;for(t=t||e.length,t>e.length&&(t=e.length),i=t-1;i>=0&&128===(192&e[i]);)i--;return 0>i?t:0===i?t:i+f[e[i]]>t?i:t}},{"./common":2}],4:[function(e,t){"use strict";function i(e,t,i,n){for(var a=65535&e|0,r=e>>>16&65535|0,s=0;0!==i;){s=i>2e3?2e3:i,i-=s;do a=a+t[n++]|0,r=r+a|0;while(--s);a%=65521,r%=65521}return a|r<<16|0}t.exports=i},{}],5:[function(e,t){t.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],6:[function(e,t){"use strict";function i(){for(var e,t=[],i=0;256>i;i++){e=i;for(var n=0;8>n;n++)e=1&e?3988292384^e>>>1:e>>>1;t[i]=e}return t}function n(e,t,i,n){var r=a,s=n+i;e=-1^e;for(var o=n;s>o;o++)e=e>>>8^r[255&(e^t[o])];return-1^e}var a=i();t.exports=n},{}],7:[function(e,t){"use strict";function i(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}t.exports=i},{}],8:[function(e,t){"use strict";var i=30,n=12;t.exports=function(e,t){var a,r,s,o,f,l,d,h,u,c,b,w,m,k,g,_,v,p,x,y,S,B,E,Z,A;a=e.state,r=e.next_in,Z=e.input,s=r+(e.avail_in-5),o=e.next_out,A=e.output,f=o-(t-e.avail_out),l=o+(e.avail_out-257),d=a.dmax,h=a.wsize,u=a.whave,c=a.wnext,b=a.window,w=a.hold,m=a.bits,k=a.lencode,g=a.distcode,_=(1<m&&(w+=Z[r++]<>>24,w>>>=x,m-=x,x=p>>>16&255,0===x)A[o++]=65535&p;else{if(!(16&x)){if(0===(64&x)){p=k[(65535&p)+(w&(1<m&&(w+=Z[r++]<>>=x,m-=x),15>m&&(w+=Z[r++]<>>24,w>>>=x,m-=x,x=p>>>16&255,!(16&x)){if(0===(64&x)){p=g[(65535&p)+(w&(1<m&&(w+=Z[r++]<m&&(w+=Z[r++]<d){e.msg="invalid distance too far back",a.mode=i;break e}if(w>>>=x,m-=x,x=o-f,S>x){if(x=S-x,x>u&&a.sane){e.msg="invalid distance too far back",a.mode=i;break e}if(B=0,E=b,0===c){if(B+=h-x,y>x){y-=x;do A[o++]=b[B++];while(--x);B=o-S,E=A}}else if(x>c){if(B+=h+c-x,x-=c,y>x){y-=x;do A[o++]=b[B++];while(--x);if(B=0,y>c){x=c,y-=x;do A[o++]=b[B++];while(--x);B=o-S,E=A}}}else if(B+=c-x,y>x){y-=x;do A[o++]=b[B++];while(--x);B=o-S,E=A}for(;y>2;)A[o++]=E[B++],A[o++]=E[B++],A[o++]=E[B++],y-=3;y&&(A[o++]=E[B++],y>1&&(A[o++]=E[B++]))}else{B=o-S;do A[o++]=A[B++],A[o++]=A[B++],A[o++]=A[B++],y-=3;while(y>2);y&&(A[o++]=A[B++],y>1&&(A[o++]=A[B++]))}break}}break}}while(s>r&&l>o);y=m>>3,r-=y,m-=y<<3,w&=(1<r?5+(s-r):5-(r-s),e.avail_out=l>o?257+(l-o):257-(o-l),a.hold=w,a.bits=m}},{}],9:[function(e,t,i){"use strict";function n(e){return(e>>>24&255)+(e>>>8&65280)+((65280&e)<<8)+((255&e)<<24)}function a(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new k.Buf16(320),this.work=new k.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function r(e){var t;return e&&e.state?(t=e.state,e.total_in=e.total_out=t.total=0,e.msg="",t.wrap&&(e.adler=1&t.wrap),t.mode=F,t.last=0,t.havedict=0,t.dmax=32768,t.head=null,t.hold=0,t.bits=0,t.lencode=t.lendyn=new k.Buf32(bt),t.distcode=t.distdyn=new k.Buf32(wt),t.sane=1,t.back=-1,A):C}function s(e){var t;return e&&e.state?(t=e.state,t.wsize=0,t.whave=0,t.wnext=0,r(e)):C}function o(e,t){var i,n;return e&&e.state?(n=e.state,0>t?(i=0,t=-t):(i=(t>>4)+1,48>t&&(t&=15)),t&&(8>t||t>15)?C:(null!==n.window&&n.wbits!==t&&(n.window=null),n.wrap=i,n.wbits=t,s(e))):C}function f(e,t){var i,n;return e?(n=new a,e.state=n,n.window=null,i=o(e,t),i!==A&&(e.state=null),i):C}function l(e){return f(e,kt)}function d(e){if(gt){var t;for(w=new k.Buf32(512),m=new k.Buf32(32),t=0;144>t;)e.lens[t++]=8;for(;256>t;)e.lens[t++]=9;for(;280>t;)e.lens[t++]=7;for(;288>t;)e.lens[t++]=8;for(p(y,e.lens,0,288,w,0,e.work,{bits:9}),t=0;32>t;)e.lens[t++]=5;p(S,e.lens,0,32,m,0,e.work,{bits:5}),gt=!1}e.lencode=w,e.lenbits=9,e.distcode=m,e.distbits=5}function h(e,t,i,n){var a,r=e.state;return null===r.window&&(r.wsize=1<=r.wsize?(k.arraySet(r.window,t,i-r.wsize,r.wsize,0),r.wnext=0,r.whave=r.wsize):(a=r.wsize-r.wnext,a>n&&(a=n),k.arraySet(r.window,t,i-n,a,r.wnext),n-=a,n?(k.arraySet(r.window,t,i-n,n,0),r.wnext=n,r.whave=r.wsize):(r.wnext+=a,r.wnext===r.wsize&&(r.wnext=0),r.whavec;){if(0===f)break e;f--,u+=a[s++]<>>8&255,i.check=_(i.check,Zt,2,0),u=0,c=0,i.mode=D;break}if(i.flags=0,i.head&&(i.head.done=!1),!(1&i.wrap)||(((255&u)<<8)+(u>>8))%31){e.msg="incorrect header check",i.mode=ht;break}if((15&u)!==T){e.msg="unknown compression method",i.mode=ht;break}if(u>>>=4,c-=4,xt=(15&u)+8,0===i.wbits)i.wbits=xt;else if(xt>i.wbits){e.msg="invalid window size",i.mode=ht;break}i.dmax=1<c;){if(0===f)break e;f--,u+=a[s++]<>8&1),512&i.flags&&(Zt[0]=255&u,Zt[1]=u>>>8&255,i.check=_(i.check,Zt,2,0)),u=0,c=0,i.mode=U;case U:for(;32>c;){if(0===f)break e;f--,u+=a[s++]<>>8&255,Zt[2]=u>>>16&255,Zt[3]=u>>>24&255,i.check=_(i.check,Zt,4,0)),u=0,c=0,i.mode=L;case L:for(;16>c;){if(0===f)break e;f--,u+=a[s++]<>8),512&i.flags&&(Zt[0]=255&u,Zt[1]=u>>>8&255,i.check=_(i.check,Zt,2,0)),u=0,c=0,i.mode=H;case H:if(1024&i.flags){for(;16>c;){if(0===f)break e;f--,u+=a[s++]<>>8&255,i.check=_(i.check,Zt,2,0)),u=0,c=0}else i.head&&(i.head.extra=null);i.mode=M;case M:if(1024&i.flags&&(m=i.length,m>f&&(m=f),m&&(i.head&&(xt=i.head.extra_len-i.length,i.head.extra||(i.head.extra=new Array(i.head.extra_len)),k.arraySet(i.head.extra,a,s,m,xt)),512&i.flags&&(i.check=_(i.check,a,m,s)),f-=m,s+=m,i.length-=m),i.length))break e;i.length=0,i.mode=K;case K:if(2048&i.flags){if(0===f)break e;m=0;do xt=a[s+m++],i.head&&xt&&i.length<65536&&(i.head.name+=String.fromCharCode(xt));while(xt&&f>m);if(512&i.flags&&(i.check=_(i.check,a,m,s)),f-=m,s+=m,xt)break e}else i.head&&(i.head.name=null);i.length=0,i.mode=j;case j:if(4096&i.flags){if(0===f)break e;m=0;do xt=a[s+m++],i.head&&xt&&i.length<65536&&(i.head.comment+=String.fromCharCode(xt));while(xt&&f>m);if(512&i.flags&&(i.check=_(i.check,a,m,s)),f-=m,s+=m,xt)break e}else i.head&&(i.head.comment=null);i.mode=P;case P:if(512&i.flags){for(;16>c;){if(0===f)break e;f--,u+=a[s++]<>9&1,i.head.done=!0),e.adler=i.check=0,i.mode=G;break;case q:for(;32>c;){if(0===f)break e;f--,u+=a[s++]<>>=7&c,c-=7&c,i.mode=ft;break}for(;3>c;){if(0===f)break e;f--,u+=a[s++]<>>=1,c-=1,3&u){case 0:i.mode=W;break;case 1:if(d(i),i.mode=tt,t===Z){u>>>=2,c-=2;break e}break;case 2:i.mode=V;break;case 3:e.msg="invalid block type",i.mode=ht}u>>>=2,c-=2;break;case W:for(u>>>=7&c,c-=7&c;32>c;){if(0===f)break e;f--,u+=a[s++]<>>16^65535)){e.msg="invalid stored block lengths",i.mode=ht;break}if(i.length=65535&u,u=0,c=0,i.mode=J,t===Z)break e;case J:i.mode=Q;case Q:if(m=i.length){if(m>f&&(m=f),m>l&&(m=l),0===m)break e;k.arraySet(r,a,s,m,o),f-=m,s+=m,l-=m,o+=m,i.length-=m;break}i.mode=G;break;case V:for(;14>c;){if(0===f)break e;f--,u+=a[s++]<>>=5,c-=5,i.ndist=(31&u)+1,u>>>=5,c-=5,i.ncode=(15&u)+4,u>>>=4,c-=4,i.nlen>286||i.ndist>30){e.msg="too many length or distance symbols",i.mode=ht;break}i.have=0,i.mode=$;case $:for(;i.havec;){if(0===f)break e;f--,u+=a[s++]<>>=3,c-=3}for(;i.have<19;)i.lens[At[i.have++]]=0;if(i.lencode=i.lendyn,i.lenbits=7,St={bits:i.lenbits},yt=p(x,i.lens,0,19,i.lencode,0,i.work,St),i.lenbits=St.bits,yt){e.msg="invalid code lengths set",i.mode=ht;break}i.have=0,i.mode=et;case et:for(;i.have>>24,kt=Et>>>16&255,gt=65535&Et,!(c>=mt);){if(0===f)break e;f--,u+=a[s++]<gt)u>>>=mt,c-=mt,i.lens[i.have++]=gt;else{if(16===gt){for(Bt=mt+2;Bt>c;){if(0===f)break e;f--,u+=a[s++]<>>=mt,c-=mt,0===i.have){e.msg="invalid bit length repeat",i.mode=ht;break}xt=i.lens[i.have-1],m=3+(3&u),u>>>=2,c-=2}else if(17===gt){for(Bt=mt+3;Bt>c;){if(0===f)break e;f--,u+=a[s++]<>>=mt,c-=mt,xt=0,m=3+(7&u),u>>>=3,c-=3}else{for(Bt=mt+7;Bt>c;){if(0===f)break e;f--,u+=a[s++]<>>=mt,c-=mt,xt=0,m=11+(127&u),u>>>=7,c-=7}if(i.have+m>i.nlen+i.ndist){e.msg="invalid bit length repeat",i.mode=ht;break}for(;m--;)i.lens[i.have++]=xt}}if(i.mode===ht)break;if(0===i.lens[256]){e.msg="invalid code -- missing end-of-block",i.mode=ht;break}if(i.lenbits=9,St={bits:i.lenbits},yt=p(y,i.lens,0,i.nlen,i.lencode,0,i.work,St),i.lenbits=St.bits,yt){e.msg="invalid literal/lengths set",i.mode=ht;break}if(i.distbits=6,i.distcode=i.distdyn,St={bits:i.distbits},yt=p(S,i.lens,i.nlen,i.ndist,i.distcode,0,i.work,St),i.distbits=St.bits,yt){e.msg="invalid distances set",i.mode=ht;break}if(i.mode=tt,t===Z)break e;case tt:i.mode=it;case it:if(f>=6&&l>=258){e.next_out=o,e.avail_out=l,e.next_in=s,e.avail_in=f,i.hold=u,i.bits=c,v(e,w),o=e.next_out,r=e.output,l=e.avail_out,s=e.next_in,a=e.input,f=e.avail_in,u=i.hold,c=i.bits,i.mode===G&&(i.back=-1);break}for(i.back=0;Et=i.lencode[u&(1<>>24,kt=Et>>>16&255,gt=65535&Et,!(c>=mt);){if(0===f)break e;f--,u+=a[s++]<>_t)],mt=Et>>>24,kt=Et>>>16&255,gt=65535&Et,!(c>=_t+mt);){if(0===f)break e;f--,u+=a[s++]<>>=_t,c-=_t,i.back+=_t}if(u>>>=mt,c-=mt,i.back+=mt,i.length=gt,0===kt){i.mode=ot;break}if(32&kt){i.back=-1,i.mode=G;break}if(64&kt){e.msg="invalid literal/length code",i.mode=ht;break}i.extra=15&kt,i.mode=nt;case nt:if(i.extra){for(Bt=i.extra;Bt>c;){if(0===f)break e;f--,u+=a[s++]<>>=i.extra,c-=i.extra,i.back+=i.extra}i.was=i.length,i.mode=at;case at:for(;Et=i.distcode[u&(1<>>24,kt=Et>>>16&255,gt=65535&Et,!(c>=mt);){if(0===f)break e;f--,u+=a[s++]<>_t)],mt=Et>>>24,kt=Et>>>16&255,gt=65535&Et,!(c>=_t+mt);){if(0===f)break e;f--,u+=a[s++]<>>=_t,c-=_t,i.back+=_t}if(u>>>=mt,c-=mt,i.back+=mt,64&kt){e.msg="invalid distance code",i.mode=ht;break}i.offset=gt,i.extra=15&kt,i.mode=rt;case rt:if(i.extra){for(Bt=i.extra;Bt>c;){if(0===f)break e;f--,u+=a[s++]<>>=i.extra,c-=i.extra,i.back+=i.extra}if(i.offset>i.dmax){e.msg="invalid distance too far back",i.mode=ht;break}i.mode=st;case st:if(0===l)break e;if(m=w-l,i.offset>m){if(m=i.offset-m,m>i.whave&&i.sane){e.msg="invalid distance too far back",i.mode=ht;break}m>i.wnext?(m-=i.wnext,bt=i.wsize-m):bt=i.wnext-m,m>i.length&&(m=i.length),wt=i.window}else wt=r,bt=o-i.offset,m=i.length;m>l&&(m=l),l-=m,i.length-=m;do r[o++]=wt[bt++];while(--m);0===i.length&&(i.mode=it);break;case ot:if(0===l)break e;r[o++]=i.length,l--,i.mode=it;break;case ft:if(i.wrap){for(;32>c;){if(0===f)break e;f--,u|=a[s++]<c;){if(0===f)break e;f--,u+=a[s++]<=z;z++)M[z]=0;for(R=0;b>R;R++)M[t[c+R]]++;for(I=A,N=n;N>=1&&0===M[N];N--);if(I>N&&(I=N),0===N)return w[m++]=20971520,w[m++]=20971520,g.bits=1,0;for(C=1;N>C&&0===M[C];C++);for(C>I&&(I=C),F=1,z=1;n>=z;z++)if(F<<=1,F-=M[z],0>F)return-1;if(F>0&&(e===s||1!==N))return-1;for(K[1]=0,z=1;n>z;z++)K[z+1]=K[z]+M[z];for(R=0;b>R;R++)0!==t[c+R]&&(k[K[t[c+R]]++]=R);if(e===s?(L=j=k,S=19):e===o?(L=l,H-=257,j=d,P-=257,S=256):(L=h,j=u,S=-1),U=0,R=0,z=C,y=m,O=I,T=0,p=-1,D=1<a||e===f&&D>r)return 1;for(var q=0;;){q++,B=z-T,k[R]S?(E=j[P+k[R]],Z=L[H+k[R]]):(E=96,Z=0),_=1<>T)+v]=B<<24|E<<16|Z|0;while(0!==v);for(_=1<>=1;if(0!==_?(U&=_-1,U+=_):U=0,R++,0===--M[z]){if(z===N)break;z=t[c+k[R]]}if(z>I&&(U&x)!==p){for(0===T&&(T=I),y+=C,O=z-T,F=1<O+T&&(F-=M[O+T],!(0>=F));)O++,F<<=1;if(D+=1<a||e===f&&D>r)return 1;p=U&x,w[p]=I<<24|O<<16|y-m|0}}return 0!==U&&(w[y+U]=z-T<<24|64<<16|0),g.bits=I,0}},{"../utils/common":2}],11:[function(e,t){"use strict";t.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],12:[function(e,t){"use strict";function i(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}t.exports=i},{}]},{},[1])(1)});
\ No newline at end of file
diff --git a/interface.coffee b/interface.coffee
new file mode 100644
index 0000000..226bd4d
--- /dev/null
+++ b/interface.coffee
@@ -0,0 +1,496 @@
+###
+interface.coffee
+
+Copyright (c) 2015 Jeongbin Park
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+###
+
+plots = []
+files = []
+joinedfile = 0
+singleendfile = 0
+
+seq_wt = ''
+seq_fancy_wt = ''
+seq_RGEN = ''
+seq_RGEN2 = ''
+filt_r = 0
+filt_n = 0
+end_range = 0
+joins_length = 0
+joins = []
+
+skip_progress = 0
+
+seq_hdr = ''
+rgen_type = 0 # 0 for Cas9, 1 for Cpf1, 2 for TALEN/ZFN/dCas9-FokI, 3 for paired Cas9, 4 for paired Cpf1
+cate = -1
+_results = []
+
+worker = undefined
+
+#prevsinglefile = ''
+#prevfile1 = ''
+#prevfile2 = ''
+
+update_progress_fastqjoin = (progress) ->
+ $('#progress_fastqjoin').css('width', progress + '%')
+
+$('#submit').click ->
+ if typeof(Worker) != "undefined"
+ worker = new Worker("/static/cas-analyzer/worker.js")
+ window.cas_analyzer_worker = worker # Keep reference of worker so that it won't garbage collected
+ else
+ alert("Your browser currently does not support features used by Cas-Analyzer. Please consider upgrading.")
+ seq_wt = new String($("#fullseq").val()).toUpperCase().replace(/\s/g,'')
+ seq_hdr = new String($("#hdrseq").val()).toUpperCase().replace(/\s/g,'')
+
+ if seq_hdr
+ n = seq_wt.search(seq_hdr[...10])+10
+ lcnt = 10
+ while seq_wt[n+lcnt-10] == seq_hdr[lcnt]
+ lcnt += 1
+
+ n = seq_wt.search(seq_hdr[-10...])-1
+ rcnt = 11
+ while seq_wt[n-rcnt+11] == seq_hdr[-rcnt...][0]
+ rcnt += 1
+
+ while seq_hdr.length-lcnt-rcnt < 10
+ lcnt -= 1
+ rcnt -= 1
+
+ seq_hdr = seq_hdr[lcnt...seq_hdr.length+1-rcnt]
+
+ # rgen_type: 0 for Cas9, 1 for Cpf1, 2 for TALEN/ZFN, 3 for dCas9-FokI, 4 for paired Cas9, 5 for paired Cpf1
+ seq_RGEN = new String($("#rgenseq").val()).toUpperCase().replace(/\s/g,'')
+ if $("#nuctype").val() == 0 and $("#nucleases").val() == 6
+ rgen_type = 1
+ else if $("#nuctype").val() == 1
+ seq_RGEN2 = new String($("#rgenseq-right").val()).toUpperCase().replace(/\s/g,'')
+ if $("#nucleases").val() == 9
+ if $("#pams").val() == 6
+ rgen_type = 5
+ else
+ rgen_type = 4
+ else if $("#nucleases").val() == 10
+ rgen_type = 3
+ else
+ rgen_type = 2
+
+ filt_n = parseInt($("#nval").val())
+ filt_r = parseInt($("#rval").val())
+ if $('#chklr').is(":checked")
+ end_range = seq_wt.length
+ else
+ end_range = parseInt($("#lrval").val())
+
+ if isNaN(end_range)
+ end_range = 70
+ if isNaN(filt_n)
+ filt_n = 1
+ if $('#chkr').is(":checked")
+ if isNaN(filt_r)
+ filt_r = 5
+ else
+ filt_r = 0
+
+ fileopt = parseInt($('#optfile').val())
+ if fileopt == 0
+ files[0] = document.getElementById("file1").files[0]
+ files[1] = document.getElementById("file2").files[0]
+ if !files[0]
+ alert('Please set file R1!')
+ return
+ if !files[1]
+ alert('Please set file R2!')
+ return
+ else if fileopt == 1
+ singleendfile = document.getElementById("file3").files[0]
+ if !singleendfile
+ alert('Please set single read file!')
+ return
+ if !seq_wt
+ alert('Please input wildtype sequence!')
+ return
+ if !seq_RGEN
+ alert('Please input RGEN sequence!')
+ return
+ if end_range <= 12
+ alert('R should be at least 12!')
+ return
+ if fileopt == 0
+ $('.file-loading-results-header').html('File1 | File2 | ')
+ $('.joinedfn1').attr('colspan', '3')
+ $('.joinedfn2').show()
+ $('.joinedfn1').html(files[0].name)
+ $('.joinedfn2').html(files[1].name)
+ else
+ $('.file-loading-results-header').html('File name | ')
+ $('.joinedfn1').attr('colspan', '6')
+ $('.joinedfn2').hide()
+ $('.singlefn').html(singleendfile.name)
+ $('.input-rgenseq').html(seq_RGEN)
+ $('.input-rval').html(String(filt_r))
+ $('.input-nval').html(String(filt_n))
+ if $('#chklr').is(':checked')
+ $('.input-lrval').html('Using both ends')
+ else
+ $('.input-lrval').html(String(end_range))
+ data = {}
+ data.msgtype = 0
+ data.seq_wt = seq_wt
+ data.rgen_type = rgen_type
+ data.seq_RGEN = seq_RGEN
+ data.seq_RGEN2 = seq_RGEN2
+ data.seq_hdr = seq_hdr
+ data.end_range = end_range
+ data.filt_n = filt_n
+ data.filt_r = filt_r
+ data.files = files
+
+ worker.onmessage = (msg) ->
+ if msg.data.msgtype == 0
+ $('.input-fullseq').html(msg.data.seq_fancy_wt)
+ location.hash = "!progress"
+ if fileopt == 0
+ $("#upper_progress").text("Fastq-join")
+ setTimeout( ->
+ #if prevsinglefile == '' and prevfile1 == (files[0].name+files[0].size) and prevfile2 == (files[1].name+files[1].size)
+ # worker.postMessage({msgtype: 3})
+ #else
+ # prevfile1 = files[0].name+files[0].size
+ # prevfile2 = files[1].name+files[1].size
+ # prevsinglefile = ''
+ # worker.postMessage({msgtype: 1, files: files})
+ #return
+ worker.postMessage({msgtype: 1, files: files})
+ , 0)
+ else if fileopt == 1
+ $("#upper_progress").text("File loading")
+ setTimeout( ->
+ #if prevsinglefile == singleendfile.name+singleendfile.size and prevfile1 == '' and prevfile2 == ''
+ # worker.postMessage({msgtype: 3})
+ #else
+ # prevsinglefile = singleendfile.name+singleendfile.size
+ # prevfile1 = ''
+ # prevfile2 = ''
+ # worker.postMessage({msgtype: 2, file: singleendfile})
+ #return
+ worker.postMessage({msgtype: 2, file: singleendfile})
+ , 0)
+ else if msg.data.msgtype == 1
+ alert(msg.data.error) # Error
+ location.hash = ""
+ else if msg.data.msgtype == 2
+ setTimeout( ->
+ $('#progress_fastqjoin').css('width', msg.data.progress + '%')
+ return
+ , 0)
+ else if msg.data.msgtype == 3
+ setTimeout( ->
+ $('#progress_analysis').css('width', msg.data.progress + '%')
+ return
+ , 0)
+ else
+ all_done(msg.data.results)
+ worker.postMessage(data)
+ return
+
+$('#btnselect10').click ->
+ $('.chkmsas').attr('checked', false)
+ for i in [0..9] by 1
+ $('#chkmsa'+i).attr('checked', true)
+ return
+
+$('#chklr').click ->
+ if $(this).is(":checked")
+ $('#lrval').attr('disabled', true)
+ else
+ $('#lrval').attr('disabled', false)
+ return
+
+$('#chkr').click ->
+ if $(this).is(":checked")
+ $('#rval').attr('disabled', false)
+ else
+ $('#rval').attr('disabled', true)
+ return
+
+$('#btnshowall').click( (e) ->
+ e.preventDefault()
+ $('.seqfilter').removeClass("active")
+ $(this).parent().addClass("active")
+ cate = -1
+ list_data()
+)
+
+$('#btnshowws').click( (e) ->
+ e.preventDefault()
+ $('.seqfilter').removeClass("active")
+ $(this).parent().addClass("active")
+ cate = 0
+ list_data()
+)
+
+$('#btnshowins').click( (e) ->
+ e.preventDefault()
+ $('.seqfilter').removeClass("active")
+ $(this).parent().addClass("active")
+ cate = 1
+ list_data()
+)
+
+$('#btnshowdel').click( (e) ->
+ e.preventDefault()
+ $('.seqfilter').removeClass("active")
+ $(this).parent().addClass("active")
+ cate = 2
+ list_data()
+)
+
+$('#showhdr').click( (e) ->
+ list_data()
+)
+
+list_data = ->
+ ishdr = $('#showhdr').is(":checked")
+ view_data = []
+ for i in [0..._results.length] by 1
+ if (cate == -1 or _results[i][6] == cate) and (!ishdr or (ishdr and _results[i][7] > 0))
+ view_data.push(_results[i])
+ load_page(0, view_data, 10)
+
+all_done = (data) ->
+ joins_count = data.joins_length
+ totlr_count = data.totlr_count
+ totn_count = data.tot_count
+ ins_count = data.cnt_ins
+ del_count = data.cnt_del
+ results = data.table
+ il = data.il
+ dl = data.dl
+ isi = data.is
+ dsi = data.ds
+ hdr = data.hdr
+
+ $('.result-joined').html(String(joins_count))
+ $('.result-totallr').html(String(totlr_count))
+ $('.result-totaln').html(String(totn_count))
+ $('.result-insertions').html(String(ins_count))
+ $('.result-deletions').html(String(del_count))
+ $('.result-indelratio').html(String(ins_count+del_count)+" ("+String(((ins_count+del_count)*100.0/totn_count).toFixed(1)) + "%)")
+ $('.result-hdrratio').html(String(hdr)+" ("+String((hdr*100.0/totn_count).toFixed(1)) + "%)")
+ rows = ''
+ if results.length == 0
+ rows = 'No entries found. |
'
+ else
+ ins_list = []
+ del_list = []
+ ws_list = []
+
+ _results = results
+
+ $('#btndownload').off()
+ $('#btndownload').on('click', ->
+ s = '#ID\tWT Sequence\tRGEN Treated Sequence\tLength\tCount\tType\tHDR\n'
+ for i in [0...results.length] by 1
+ entry = results[i]
+ s += entry[0] + '\t' + entry[1] + '\t' + entry[2] + '\t' + entry[4] + '\t' + entry[5] + '\t'
+ if entry[6] == 0
+ s += 'WT or Sub'
+ else if entry[6] == 1
+ s += 'Ins'
+ else
+ s += 'del'
+ s += '\t'
+ if entry[7] < -1
+ s += 'N/A'
+ else if entry[7] == -1
+ s += 'X'
+ else
+ s += 'O'
+ s += '\n'
+ saveTextData(s, 'result.txt')
+ return
+ )
+
+ draw_plots = ->
+ if ($("#placeholder_is").width())
+ load_page(0, results, 10)
+ plots.push(
+ $.plot("#placeholder_is", [
+ { data: isi, color: "#DE000F" }
+ ], {
+ series: {
+ bars: { show: true },
+ },
+ grid: {
+ hoverable: true
+ },
+ xaxis: {
+ #transform: (v) -> return if v == 0 then v else Math.log(v),
+ axisLabel: "Size",
+ axisLabelUseCanvas: true,
+ axisLabelFontFamily: 'Arial',
+ axisLabelPadding: 10
+ },
+ yaxis: {
+ axisLabel: "Count",
+ axisLabelUseCanvas: true,
+ axisLabelFontFamily: 'Arial',
+ axisLabelPadding: 8
+ }
+ })
+ )
+ plots.push(
+ $.plot("#placeholder_ds", [
+ { data: dsi, color: "#DE000F" }
+ ], {
+ series: {
+ bars: { show: true },
+ },
+ grid: {
+ hoverable: true
+ },
+ xaxis: {
+ #transform: (v) -> return if v == 0 then v else Math.log(v),
+ axisLabel: "Size",
+ axisLabelUseCanvas: true,
+ axisLabelFontFamily: 'Arial',
+ axisLabelPadding: 10
+ },
+ yaxis: {
+ axisLabel: "Count",
+ axisLabelUseCanvas: true,
+ axisLabelFontFamily: 'Arial',
+ axisLabelPadding: 8
+ }
+ })
+ )
+ plots.push(
+ $.plot("#placeholder_il", [
+ { data: il, color: "#5482FF" }
+ ], {
+ series: {
+ bars: { show: true },
+ },
+ grid: {
+ hoverable: true
+ },
+ xaxis: {
+ axisLabel: "Position",
+ axisLabelUseCanvas: true,
+ axisLabelFontFamily: 'Arial',
+ axisLabelPadding: 10
+ },
+ yaxis: {
+ axisLabel: "Ratio (%)",
+ axisLabelUseCanvas: true,
+ axisLabelFontFamily: 'Arial',
+ axisLabelPadding: 8
+ }
+ })
+ )
+ plots.push(
+ $.plot("#placeholder_dl", [
+ { data: dl, color: "#5482FF" }
+ ], {
+ series: {
+ bars: { show: true },
+ },
+ grid: {
+ hoverable: true
+ },
+ xaxis: {
+ axisLabel: "Position",
+ axisLabelUseCanvas: true,
+ axisLabelFontFamily: 'Arial',
+ axisLabelPadding: 10
+ },
+ yaxis: {
+ axisLabel: "Ratio (%)",
+ axisLabelUseCanvas: true,
+ axisLabelFontFamily: 'Arial',
+ axisLabelPadding: 8
+ }
+ })
+ )
+ $("").css({
+ position: "absolute",
+ display: "none",
+ border: "1px solid #fdd",
+ padding: "2px",
+ "background-color": "#fee",
+ opacity: 0.80
+ }).appendTo("body")
+ $(".plotarea").each( ->
+ $(this).bind("plothover", (evt, pos, item) ->
+ if (item)
+ x = item.datapoint[0]
+ if this.id == "placeholder_ds" or this.id == "placeholder_is"
+ y = item.datapoint[1]
+ else
+ y = item.datapoint[1].toFixed(3)
+ $("#tooltip_plot").html("(" + x + ", " + y + ")").css({top: item.pageY+5, left: item.pageX+5}).fadeIn(200)
+ else
+ $("#tooltip_plot").hide()
+ return
+ )
+ return
+ )
+ else
+ setTimeout(draw_plots, 200)
+ return
+ setTimeout(draw_plots, 200)
+
+ location.hash = "!result"
+ skip_progress = 1
+ return
+clear_plots = ->
+ for plot in plots
+ plot.shutdown()
+ plots = []
+window.onload = ->
+ location.hash = "!"
+ return
+
+window.onhashchange = ->
+ $('#progress_fastqjoin').css('width', '0')
+ $('#progress_analysis').css('width', '0')
+ if location.hash == "#!progress"
+ if skip_progress
+ skip_progress = 0
+ location.hash = "!"
+ else
+ $("#inputform").hide()
+ $("#progress").show()
+ else if location.hash == "#!result"
+ $("#progress").hide()
+ $("#result").show()
+ else
+ worker.terminate()
+ clear_plots()
+ $("#progress").hide()
+ $("#result").hide()
+ $("#inputform").show()
+ $('.seqfilter').removeClass("active")
+ $('#btnshowall').parent().addClass("active")
+ return
diff --git a/worker.js b/worker.js
new file mode 100644
index 0000000..6e5569d
--- /dev/null
+++ b/worker.js
@@ -0,0 +1,145 @@
+importScripts('core/pako_inflate.min.js');
+importScripts('core/jbfilereader.js');
+importScripts('core/fastq-join.js');
+importScripts('core/needle.js');
+importScripts('core/miseq-analyzer.js');
+
+var rgen_type, seq_RGEN, seq_RGEN2, seq_wt, seq_hdr, end_range, filt_n, filt_r, files;
+
+onmessage = function(msg) {
+ if (msg.data.msgtype == 0) {
+ rgen_type = msg.data.rgen_type;
+ seq_RGEN = msg.data.seq_RGEN;
+ seq_RGEN2 = msg.data.seq_RGEN2;
+ seq_wt = msg.data.seq_wt;
+ seq_hdr = msg.data.seq_hdr;
+ end_range = msg.data.end_range;
+ filt_n = msg.data.filt_n;
+ filt_r = msg.data.filt_r;
+ files = msg.data.files;
+
+ if (rgen_type < 2) {
+ pattern = new RegExp("(" + seq_RGEN + ")|(" + revcompstr(seq_RGEN) + ")");
+ m = pattern.exec(seq_wt);
+ if (m) {
+ if (rgen_type === 0) {
+ if (m[1]) {
+ bp = m.index + seq_RGEN.length - 3;
+ } else {
+ bp = m.index + 3;
+ }
+ } else if (rgen_type === 1) {
+ if (m[1]) {
+ bp = m.index + 21;
+ } else {
+ bp = m.index + seq_RGEN.length - 16;
+ }
+ }
+ } else {
+ self.postMessage({msgtype: 1, error: "Couldn't find RGEN site in WT sequence!"});
+ return;
+ }
+ } else {
+ if (rgen_type === 2) {
+ pattern_1 = new RegExp("(" + seq_RGEN + ")");
+ pattern_2 = new RegExp("(" + seq_RGEN2 + ")");
+ } else {
+ pattern_1 = new RegExp("(" + seq_RGEN + ")|(" + revcompstr(seq_RGEN) + ")");
+ pattern_2 = new RegExp("(" + seq_RGEN2 + ")|(" + revcompstr(seq_RGEN2) + ")");
+ }
+ m_1 = pattern_1.exec(seq_wt);
+ m_2 = pattern_2.exec(seq_wt);
+ if (m_1 && m_2) {
+ if (m_1.index > m_2.index) {
+ self.postMessage({msgtype: 1, error: "Position of left site is bigger than that of right site!"});
+ return;
+ }
+ if (rgen_type < 4) {
+ bp = Math.round((m_1.index + m_2.index + seq_RGEN2.length) / 2);
+ } else if (rgen_type === 4) {
+ if (m_1[1]) {
+ bp_1 = m.index + seq_RGEN.length - 3;
+ } else {
+ bp_1 = m.index + 3;
+ }
+ if (m_2[1]) {
+ bp_2 = m.index + seq_RGEN2.length - 3;
+ } else {
+ bp_2 = m.index + 3;
+ }
+ bp = Math.round((bp_1 + bp_2) / 2);
+ } else {
+ if (m_1[1]) {
+ bp_1 = m.index + 21;
+ } else {
+ bp_1 = m.index + seq_RGEN.length - 16;
+ }
+ if (m_2[1]) {
+ bp_2 = m.index + 21;
+ } else {
+ bp_2 = m.index + seq_RGEN2.length - 16;
+ }
+ bp = Math.round((bp_1 + bp_2) / 2);
+ }
+ } else {
+ self.postMessage({msgtype: 1, error: "Couldn't find both sites in WT sequence!"});
+ return;
+ }
+ }
+ start_pos = bp - end_range;
+ end_pos = bp + end_range;
+ if (start_pos < 0) {
+ start_pos = 0;
+ }
+ if (end_pos > seq_wt.length) {
+ end_pos = seq_wt.length;
+ }
+ s_seq = seq_wt.slice(bp - filt_r, bp + filt_r);
+ seq_range = seq_wt.slice(start_pos, end_pos);
+ pri_for = seq_range.slice(0, pri_len);
+ pri_back = seq_range.slice(-pri_len);
+ pri_for_patterns = [];
+ pri_back_patterns = [];
+ for (i = 0; i < pri_len; i++) {
+ pri_for_patterns.push(pri_for.slice(0, i) + '[AGCT]' + pri_for.slice(i + 1));
+ pri_back_patterns.push(pri_back.slice(0, i) + '[AGCT]' + pri_back.slice(i + 1));
+ }
+ min = function(a, b) {
+ if (a < b) {
+ return a;
+ } else {
+ return b;
+ }
+ };
+ max = function(a, b) {
+ if (a > b) {
+ return a;
+ } else {
+ return b;
+ }
+ };
+ seq_fancy_wt = seq_wt.slice(0, start_pos);
+ seq_fancy_wt += '' + seq_wt.slice(start_pos, min(start_pos + pri_len, bp - filt_r)) + '';
+ seq_fancy_wt += seq_wt.slice(start_pos + pri_len, min(m.index, bp - filt_r));
+ seq_fancy_wt += '' + seq_wt.slice(m.index, bp - filt_r) + '';
+ seq_fancy_wt += '' + seq_wt.slice(bp - filt_r, bp + filt_r) + '';
+ seq_fancy_wt += '' + seq_wt.slice(bp + filt_r, m.index + seq_RGEN.length) + '';
+ seq_fancy_wt += seq_wt.slice(max(m.index + seq_RGEN.length, bp + filt_r), end_pos - pri_len);
+ seq_fancy_wt += '' + seq_wt.slice(max(end_pos - pri_len, bp + filt_r), end_pos) + '';
+ seq_fancy_wt += seq_wt.slice(end_pos);
+
+ set_primer_patterns(pri_for_patterns, pri_back_patterns);
+
+ self.postMessage({msgtype: 0, seq_fancy_wt: seq_fancy_wt});
+ } else if (msg.data.msgtype == 1 || msg.data.msgtype == 2) {
+ empty_cache();
+ pgcallback1 = function(p) { self.postMessage({msgtype: 2, progress: p}); };
+ pgcallback2 = function(p) { self.postMessage({msgtype: 3, progress: p}); };
+ if (msg.data.msgtype == 1)
+ run_fastq_join(msg.data.files, pgcallback1, process_chunk, true);
+ else
+ parse_file(msg.data.file, pgcallback1, process_chunk);
+ data = run_cas_analyser(seq_range, seq_hdr, filt_n, filt_r, pgcallback2);
+ self.postMessage({msgtype: 4, results: data});
+ }
+}