Last active
August 29, 2015 14:06
-
-
Save coronin/3fbdec65f0dfdae59b56 to your computer and use it in GitHub Desktop.
run nicely with ots_server and Web Blat
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> | |
<title>crispr scanner, made by Liang Cai</title> | |
<style type="text/css" media="screen"><!-- | |
body{margin:25px;padding:0;font-family:Arial,Helvetica,sans-serif;font-size:100%;line-height:1.5} | |
article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block} | |
h1,h2,h3,h4{margin:1em 0 .5em;line-height:1.25;font-weight:700} | |
h1{font-size:2em} | |
h2{font-size:1.5em} | |
h3{font-size:1.2em} | |
h4{font-size:1em} | |
ol,ul{margin:1em 0;padding:1em;background:#eee;list-style-type:none;font-family:"Courier New",Courier,monospace} | |
p{margin:1em 0} | |
blockquote{margin:1em 40px} | |
figure{margin:1em 0} | |
a{text-decoration:underline} | |
a:link{color:#00E} | |
a:visited{color:#551A8B} | |
a:active{color:#E00} | |
a:active,a:hover{outline:0} | |
a img{border:none} | |
cite,q{font-style:italic} | |
q:after,q:before{content:""} | |
sub,sup{line-height:0} | |
fieldset{margin:0;padding:0;border:none} | |
button,input,select{vertical-align:middle} | |
table{border-collapse:collapse} | |
td,th{padding:1px;vertical-align:top;text-align:left} | |
td:first-child,th:first-child{empty-cells:hide} | |
.blat{font-size:0.8em} | |
.line{position:fixed;bottom:0;width:12px;height:20px;font-size:8px} | |
--></style> | |
</head> | |
<body> | |
<h1>crispr scanner, made by Liang Cai</h1> | |
<p>Cas9 species = S. pyogenes (PAM = NGG)</p> | |
<p>Use <a href="https://github.com/htgt/CRISPR-Analyser">ots_server</a> as data source | |
<span id="server_status"><br/></span></p> | |
<hr/> | |
<p> | |
<em>species</em><br/> | |
<input type="radio" name="species" value="dog" id="species_dog" checked /><label for="species_dog">dog</label><br/> | |
<input type="radio" name="species" value="human" id="species_human" /><label for="species_human">human</label><br/> | |
<input type="radio" name="species" value="mouse" id="species_mouse" /><label for="species_mouse">mouse</label> | |
</p> | |
<hr/> | |
<p> | |
option 1, <em>check a gRNA sequence</em><br/> | |
<input type="text" name="gRNA" size="20" id="gRNA_seq" /> | |
</p> | |
<p> | |
option 2, <em>search gRNAs in a genomic sequence</em> <input type="checkbox" id="rigorous" /><span id="rigorous_label">only four</span><br/> | |
<!-- human EMX1 locus : ggaggaagggcctgagtccgagcagaagaagaagggctcccatcacatcaaccggtggcgcattgccacgaagcaggccaatggggaggacatcgatgtcacctccaatgactagggtgggc --> | |
<textarea cols="60" rows="12" id="target_seq"></textarea> | |
</p> | |
<hr/> | |
<p> | |
<input type="submit" value="submit" id="submit" /> | |
<span id="progress" style="background:yellow;font-size:75%;margin-left:25px"></span> | |
</p> | |
<div><ul id="ots_result"></ul></div> | |
<div id="graph_show"></div> | |
<script src="jquery-2.1.1.min.js"></script> | |
<script> | |
var ots_addr = 'http://localhost:8080', | |
blat_addr = 'http://localhost/cgi-bin/webBlat', | |
rigorous = false, | |
pix_size = 1; | |
function quick_e(g, idx, pam, antiparallel) { | |
var e = ''; | |
if (idx && antiparallel) { | |
e = '<span style="color:#f00;background:white">-</span> <i>'+pam+'</i> <b>'+g+'</b> : #'+(idx+3)+', '; | |
} else if (idx) { | |
e = '<span style="color:#0f0;background:white">+</span> <b>'+g+'</b> <i>'+pam+'</i> : #'+(idx-21)+', '; | |
} else { | |
e = '5-<b>'+g+'</b>-3 : '; | |
} | |
return e; | |
} | |
function blat_23nt(idx, s) { | |
var seq = $('#q'+idx).text().split(' : ')[0].replace(/[^ATgC]/g, ''); | |
$.ajax({ | |
type: 'POST', | |
url: blat_addr, | |
dataType: 'html', | |
data: {'wb_db':s,'wb_seq':seq,'wb_qType':'DNA','wb_sort':'query,score','wb_output':'psl no header'}, | |
success: function (d) { | |
var psl = $(d).find('TT').text(), pslsub; | |
if (psl.substr(0,2) !== '23') { | |
console.log(seq); | |
console.log( 'blat output : '+psl.replace(/\t/g, ' ') ); | |
$('#q'+idx).remove(); // not a genomic seq, most likely on different exons | |
$('.line'+idx).remove(); | |
} else { | |
pslsub = psl.split("query\t")[1].split("\t"); | |
$('#blat'+idx).text('['+pslsub[3]+' '+pslsub[5]+'-'+pslsub[6]+']'); | |
} | |
return true; | |
}, | |
error: function () { | |
$('#blat'+idx).text('[please verify 23nt by Blat or Blast]'); | |
return false; | |
} | |
}); | |
} | |
function search_an_id(s, a, g, idx, pam, antiparallel) { | |
$.getJSON(ots_addr+'/api/off_targets?callback=?', | |
{'species':s, 'ids':a}, | |
function (d) { | |
var b = d[''+a].off_target_summary, | |
c = eval('(' + b + ')'), e; | |
if (c[0] === 0) { | |
if (idx) { | |
$('#q'+idx).remove(); | |
} else { | |
$('#ots_result').append('<li>5-<b>'+g+'</b>-3 : ignore. zero hit in '+s+'</li>'); | |
} | |
} else if (c[0] > 1) { | |
if (idx) { | |
$('#q'+idx).remove(); | |
} else { | |
$('#ots_result').append('<li>5-<b>'+g+'</b>-3 : alert! do not use, '+c[0]+' exact hits</li>'); | |
} | |
} else if (c[1] || c[2]) { | |
if (idx) { | |
$('#q'+idx).remove(); | |
} else { | |
$('#ots_result').append('<li>5-<b>'+g+'</b>-3 : warning! one '+c[1]+', two '+c[2]+'</li>'); | |
} | |
} else if (c[3]) { | |
e = quick_e(g, idx, pam, antiparallel) + 'fine. three '+c[3]+', four '+c[4]; | |
if (idx && rigorous) { | |
$('#q'+idx).remove(); | |
} else if (idx) { | |
$('#q'+idx).html(e+' <span class="blat" id="blat'+idx+'"></span>'); | |
if (antiparallel) { | |
$('#graph_show').append('<div class="line line'+idx+'" style="background-color:rgba(255,100,100,0.6);text-align:left;border-left:1px solid #999;left:'+(25+idx*pix_size)+'px">'+(idx+3)+'</div>'); | |
} else { | |
$('#graph_show').append('<div class="line line'+idx+'" style="background-color:rgba(100,255,100,0.6);text-align:right;border-right:1px solid #999;left:'+(25+idx*pix_size)+'px">'+(idx-21)+'</div>'); | |
} | |
blat_23nt(idx, s); | |
} else { | |
$('#ots_result').append('<li>'+e+'</li>'); | |
} | |
} else { | |
e = quick_e(g, idx, pam, antiparallel) + 'good. four '+c[4]; | |
if (idx) { | |
$('#q'+idx).html(e+' <span class="blat" id="blat'+idx+'"></span>'); | |
if (antiparallel) { | |
$('#graph_show').append('<div class="line line'+idx+'" style="background-color:rgba(255,0,0,0.6);text-align:left;border-left:1px solid #333;left:'+(25+idx*pix_size)+'px">'+(idx+3)+'</div>'); | |
} else { | |
$('#graph_show').append('<div class="line line'+idx+'" style="background-color:rgba(0,255,0,0.6);text-align:right;border-right:1px solid #333;left:'+(25+idx*pix_size)+'px">'+(idx-21)+'</div>'); | |
} | |
blat_23nt(idx, s); | |
} else { | |
$('#ots_result').append('<li>'+e+'</li>'); | |
} | |
} | |
}).done(function () { | |
$('#progress').append(' .'); | |
}); | |
} | |
function search_seq(s, g, idx, pam, antiparallel) { | |
return $.getJSON(ots_addr+'/api/search?callback=?', | |
{'species':s, 'seq':g}, | |
function (d) { | |
if (d.length > 1) { | |
if (!idx) { $('#ots_result').append('<li>5-<b>'+s+'</b>-3 : '+d.length+' hits</li>'); } | |
} else if (d.length === 1) { | |
if (idx && antiparallel) { | |
$('#ots_result').append('<li id="q'+idx+'">...</li>'); | |
} else if (idx) { | |
$('#ots_result').append('<li id="q'+idx+'">...</li>'); | |
} | |
search_an_id(s, d[0], g, idx, pam, antiparallel); | |
} else { | |
if (!idx) { $('#ots_result').append('<li>5-<b>'+g+'</b>-3 : ignore. zero hit in '+s+'</li>'); } | |
} | |
}); | |
} | |
function plus_strand_search(s, t) { | |
var pam_seq = 'gg', // NGG | |
t1 = t.indexOf(pam_seq), tsub, tsub1, | |
t2 = t.lastIndexOf(pam_seq); | |
while (t1 < 21) { | |
t1 += 1; | |
tsub = t.substr(t1); | |
tsub1 = tsub.indexOf(pam_seq); | |
if (tsub1 > -1) { | |
t1 += tsub1; | |
} else { break; } | |
} | |
if (t1 > t2) { | |
$('#progress').append(', none in the + strand'); | |
} else { | |
$('#progress').append('; will process the + strand between '+t1+' ~ '+t2); | |
var seqs = [], idxs = [], ti, tt, pams = []; | |
for (ti = t1; ti <= t2; ti += 1) { | |
if (t.substr(ti, 2) === pam_seq) { | |
tt = t.substr(ti-21, 20); | |
if (seqs.indexOf(tt) === -1) { | |
seqs.push(tt); | |
idxs.push(ti); | |
pams.push( t.substr(ti-1, 3) ); | |
} | |
} | |
} | |
defrs_search(s, seqs, idxs, pams, false); | |
} | |
} | |
function minus_strand_search(s, t) { | |
var pam_seq = 'CC', // CCN | |
t1 = t.indexOf(pam_seq), tsub, tsub2, | |
t2 = t.lastIndexOf(pam_seq); | |
while ((t.length-t2) < 21) { | |
tsub = t.substring(0, t2-1); | |
tsub2 = tsub.lastIndexOf(pam_seq); | |
t2 = -1 | |
if (tsub2 > -1) { | |
t2 = tsub2; | |
} else { break; } | |
} | |
if (t2 === -1) { | |
$('#progress').append(', none in the - strand'); | |
} else { | |
$('#progress').append('; will process the - strand between '+t1+' ~ '+t2); | |
var seqs = [], idxs = [], ti, tt, pams = []; | |
for (ti = t1; ti <= t2; ti += 1) { | |
if (t.substr(ti, 2) === pam_seq) { | |
tt = t.substr(ti+3, 20); | |
if (seqs.indexOf(tt) === -1) { | |
seqs.push(tt); | |
idxs.push(ti); | |
pams.push( t.substr(ti, 3) ); | |
} | |
} | |
} | |
defrs_search(s, seqs, idxs, pams, true); | |
} | |
} | |
function defrs_search(s, seqs, idxs, pams, antiparallel) { | |
var defrs = []; | |
$.each(seqs, function (iV, ele) { | |
defrs.push( search_seq(s, ele, idxs[iV], pams[iV], antiparallel) ); | |
}); | |
$('#progress').append(', looped'); | |
$.when(defrs).done(function () { | |
$('#progress').append(', queued'); | |
}); | |
} | |
function anti_parallel(t) { | |
var apt_list = [], | |
t_list = t.split(''); | |
$.each(t_list, function (iV, ele) { | |
if (ele === 'A') { | |
apt_list.unshift( 'T' ); | |
} else if (ele === 'T') { | |
apt_list.unshift( 'A' ); | |
} else if (ele === 'g') { | |
apt_list.unshift( 'C' ); | |
} else if (ele === 'C') { | |
apt_list.unshift( 'g' ); | |
} | |
}); | |
return apt_list.join(''); | |
} | |
function check_server() { | |
$.getJSON(ots_addr+'/api/search?callback=?', | |
{'seq':'TTAATTGTTTAGCAGTGTCA', 'species':'mouse'}, | |
function (d) { | |
if (d.length === 1) { | |
$('#server_status').append('the server is running'); | |
$('#server_status').css({'background':'#eee','color':'green'}); | |
} else { | |
$('#server_status').append('SERVER ERROR'); | |
$('#server_status').css({'background':'yellow','color':'red'}); | |
$('#submit').hide(); | |
} | |
}); | |
} | |
$(document).ready(function () { | |
check_server(); | |
$('#submit').on('click', function (event) { | |
$('#ots_result').html(''); | |
$('#graph_show').html(''); | |
$('#progress').text('ing...'); | |
var s = $('input:checked').val(), | |
g = $('#gRNA_seq').val(), | |
t = $('#target_seq').val(); | |
if (g) { | |
$('#target_seq').val(''); | |
rigorous = false; | |
$('#rigorous').attr('checked', false); | |
$('#rigorous_label').show(); | |
g = g.replace(/[^atgc]/gi, '').toUpperCase().replace(/G/g, 'g'); | |
if (g && g.length === 20) { | |
search_seq(s, g); | |
$('#progress').text('done job1!'); | |
} else { | |
$('#progress').text('!! please input a 20-nt seq :-p'); | |
$('#gRNA_seq').focus(); | |
} | |
} else if (t) { | |
$('#gRNA_seq').val(''); | |
if( $('#rigorous').is(':checked') ) { | |
rigorous = true; | |
$('#rigorous_label').show(); | |
} else { | |
rigorous = false; | |
$('#rigorous_label').hide(); | |
} | |
t = t.replace(/[^atgc]/gi, '').toUpperCase().replace(/G/g, 'g'); | |
if ( $('#graph_show').width() > t.length ) { | |
pix_size = $('#graph_show').width() / t.length; | |
} | |
$('#progress').text('job2 starts (if nothing shown means no hit)'); | |
plus_strand_search(s, t); | |
$('#progress').append('; now the anti-parallel'); | |
minus_strand_search(s, t); | |
} else { | |
$('#progress').text('!! please input something correct :-p'); | |
$('#gRNA_seq').focus(); | |
} | |
event.preventDefault(); | |
}); | |
}); | |
</script> | |
</body> | |
</html> |
now, with local Web Blat support
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
now, it is public