Template:Team:UC Davis/MutantWidget
From 2011.igem.org
(Difference between revisions)
(33 intermediate revisions not shown) | |||
Line 4: | Line 4: | ||
<script> | <script> | ||
//Painstakingly coded by Keegan Owsley. Feel free to use it, but it might burn your house down. | //Painstakingly coded by Keegan Owsley. Feel free to use it, but it might burn your house down. | ||
+ | |||
+ | function rerender() | ||
+ | { | ||
+ | |||
+ | camera.position.x = 250*Math.cos(theta); | ||
+ | camera.position.y = 250*Math.sin(theta); | ||
+ | if(phi < Math.PI/2) | ||
+ | { | ||
+ | phi = Math.PI/2; | ||
+ | } | ||
+ | if(phi > 3*Math.PI/4) | ||
+ | { | ||
+ | phi = 3*Math.PI/4; | ||
+ | } | ||
+ | camera.position.z = -250*Math.cos(phi); | ||
+ | zaxislabel.rotation.y = Math.PI/2 - Math.atan2((zaxislabel.position.y-camera.position.y),(zaxislabel.position.x-camera.position.x)); | ||
+ | for(var i =0; i < yticklabels.length;i++) | ||
+ | { | ||
+ | yticklabels[i].rotation.y = -Math.PI/2 + Math.atan2((yticklabels[i].position.y-camera.position.y),(yticklabels[i].position.x-camera.position.x)); | ||
+ | } | ||
+ | for(var i =0; i < xticklabels.length;i++) | ||
+ | { | ||
+ | xticklabels[i].rotation.y = -Math.PI/2 + Math.atan2((xticklabels[i].position.y-camera.position.y),(xticklabels[i].position.x-camera.position.x)); | ||
+ | } | ||
+ | |||
+ | |||
+ | //renderer.clear(); | ||
+ | renderer.render(scene, camera); | ||
+ | } | ||
+ | |||
+ | function update3DPlotMeshes() | ||
+ | { | ||
+ | var datameshes = []; | ||
+ | var datalines = []; | ||
+ | var errbars = []; | ||
+ | $('#mw_selectmenu td').each( | ||
+ | function(index) | ||
+ | { | ||
+ | if($(this).hasClass("selected")) | ||
+ | { | ||
+ | if(plot_mesh[index]) | ||
+ | { | ||
+ | datameshes.push(plot_mesh[index]); | ||
+ | datalines.push(meshchildren[index]); | ||
+ | errbars.push(errorbars_3d[index]); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | ); | ||
+ | for(var i = 0;i < plot_mesh.length; i++) | ||
+ | { | ||
+ | plot_obj.removeChild(plot_mesh[i]); | ||
+ | plot_obj.removeChild(errorbars_3d[i]); | ||
+ | plot_obj.removeChild(meshchildren[i]); | ||
+ | } | ||
+ | for(var i=0;i < datameshes.length; i++) | ||
+ | { | ||
+ | plot_obj.addChild(datameshes[i]); | ||
+ | plot_obj.addChild(errbars[i]); | ||
+ | plot_obj.addChild(datalines[i]); | ||
+ | } | ||
+ | |||
+ | renderer.render(scene, camera); | ||
+ | } | ||
// RGB <-> HSL conversions based on equations from wikipedia. | // RGB <-> HSL conversions based on equations from wikipedia. | ||
Line 9: | Line 73: | ||
function RGB2HSL(r,g,b) | function RGB2HSL(r,g,b) | ||
{ | { | ||
- | + | var alpha = 1/2*(2*r-g-b); | |
- | + | var beta = Math.sqrt(3)/2*(g-b); | |
- | + | var C = Math.sqrt(alpha^2 + beta^2); | |
- | + | var h = Math.atan2(beta, alpha); | |
- | + | if(h < 0) | |
- | + | { | |
- | + | h += 2*Math.PI; | |
- | + | } | |
- | + | var l = 0.3*r + 0.59*g + 0.11*b; | |
- | + | if(C > 0) | |
- | + | { | |
- | + | s = C/(1 - Math.abs(2*l-1)); | |
- | + | } else | |
- | + | { | |
- | + | s = 0; | |
- | + | } | |
- | + | ||
- | + | return {h:h,s:s,l:l}; | |
} | } | ||
function HSL2RGB(h,s,l) | function HSL2RGB(h,s,l) | ||
{ | { | ||
- | + | ||
- | + | var C = (1-Math.abs(2*l-1))*s; | |
- | + | var Hprime = h / Math.PI*3; | |
- | + | var X = C*(1 - Math.abs(Hprime%2-1)); | |
- | + | if(h < 0) { | |
- | + | var r = g = b = 0; | |
- | + | } else if(h < 1) { | |
- | + | var r = C, g = X, b = 0; | |
- | + | } else if(h < 2) { | |
- | + | var r = X, g = C, b = 0; | |
- | + | } else if(h < 3) { | |
- | + | var r = 0, g = C, b = X; | |
- | + | } else if(h < 4) { | |
- | + | var r = 0, g = X, b = C; | |
- | + | } else if(h < 5) { | |
- | + | var r = X, g = 0, b = C; | |
- | + | } else if(h < 6) { | |
- | + | var r = C, g = 0, b = X; | |
- | + | } | |
- | + | m = l - C/2; | |
- | + | r = r + m; | |
- | + | g = g + m; | |
- | + | b = b + m; | |
- | + | return {r:r, g:g, b:b} | |
} | } | ||
Line 66: | Line 130: | ||
function interp2(x1, y1, x2, y2, z0, z1, z2, z3, x, y) | function interp2(x1, y1, x2, y2, z0, z1, z2, z3, x, y) | ||
{ | { | ||
- | + | fr1 = (x-x1)/(x2-x1)*z1 + (x2-x)/(x2-x1)*z0; | |
- | + | fr2 = (x-x1)/(x2-x1)*z3 + (x2-x)/(x2-x1)*z2; | |
if(!fr1 || !fr2) | if(!fr1 || !fr2) | ||
{ | { | ||
alert("MAJOR INTERPOLATION PROBLEMS!\nx1:"+x1+"\ny1:"+y1+"\nx2:"+x2+"\ny2:"+y2+"\nzs:"+z0+","+z1+","+z2+","+z3+"\n("+x+","+y+")"); | alert("MAJOR INTERPOLATION PROBLEMS!\nx1:"+x1+"\ny1:"+y1+"\nx2:"+x2+"\ny2:"+y2+"\nzs:"+z0+","+z1+","+z2+","+z3+"\n("+x+","+y+")"); | ||
} | } | ||
- | + | return ((y-y1)/(y2-y1)*fr2 + (y2-y)/(y2-y1)*fr1); | |
} | } | ||
function colorRamp(value, colormap) | function colorRamp(value, colormap) | ||
{ | { | ||
- | + | if(value > 1) | |
- | + | { | |
- | + | value = 1; | |
- | + | } | |
- | + | if(value < 0) | |
- | + | { | |
- | + | value = 0; | |
- | + | } | |
- | + | var maxval = colormap.length-1; | |
- | + | var newval = value*maxval; | |
- | + | var highval = Math.ceil(newval); | |
- | + | var lowval = highval - 1; | |
- | + | if(highval == 0) | |
- | + | { | |
- | + | lowval = 0; | |
- | + | highval = 1; | |
- | + | } | |
- | + | lowcolor = RGB2HSL(colormap[lowval][0], colormap[lowval][1], colormap[lowval][2]); | |
- | + | highcolor = RGB2HSL(colormap[highval][0], colormap[highval][1], colormap[highval][2]); | |
- | + | var h = lowcolor.h*(highval - newval) + highcolor.h*(newval - lowval); | |
- | + | var s = lowcolor.s*(highval - newval) + highcolor.s*(newval - lowval); | |
- | + | var v = lowcolor.l*(highval - newval) + highcolor.l*(newval - lowval); | |
//s = lowcolor.s; | //s = lowcolor.s; | ||
//v = lowcolor.l; | //v = lowcolor.l; | ||
- | + | newcolor = HSL2RGB(h,s,v); | |
- | + | newcolor.r = colormap[lowval][0]*(highval - newval) + colormap[highval][0]*(newval - lowval); | |
- | + | newcolor.g = colormap[lowval][1]*(highval - newval) + colormap[highval][1]*(newval - lowval); | |
- | + | newcolor.b = colormap[lowval][2]*(highval - newval) + colormap[highval][2]*(newval - lowval); | |
- | + | return [newcolor.r, newcolor.g, newcolor.b]; | |
} | } | ||
Line 176: | Line 240: | ||
[0.56349, 0.00000, 0.00000], | [0.56349, 0.00000, 0.00000], | ||
[0.50000, 0.00000, 0.00000]]; | [0.50000, 0.00000, 0.00000]]; | ||
+ | |||
+ | //cool_color_ramp = [[0,0,0], [0,0,1], [1,1,1]]; | ||
var WIDTH = 650; | var WIDTH = 650; | ||
Line 185: | Line 251: | ||
mutantcolors = ["white", "#ff6666", "orange", "yellow", "#66ff66", "#66ffff", "#ddaaff", "pink"]; | mutantcolors = ["white", "#ff6666", "orange", "yellow", "#66ff66", "#66ffff", "#ddaaff", "pink"]; | ||
+ | mutantcolors_hex = [0xffffff, 0xff6666, 0xffa500, 0xffff00, 0x66ff66, 0x66ffff, 0xddaaff, 0xffc0cb]; | ||
selectedColor = "orange"; | selectedColor = "orange"; | ||
widget_mode = "2D"; | widget_mode = "2D"; | ||
have_3d_data = false; | have_3d_data = false; | ||
$(document).ready(function(){ | $(document).ready(function(){ | ||
- | + | $("#mutantwidget").append('<div id="mw_selectmenu"/>'); | |
- | + | $("#mutantwidget").append('<div id="mw_optionsmenu"><table id="mw_optionstable"></table></div>'); | |
- | + | $("#mw_selectmenu").append("<table id='seltable'/>"); | |
- | + | $('#mutantwidget h3').wrapInner('<td/>').children().unwrap().css({opacity:.3}).wrap('<tr/>'); | |
- | + | $('#mutantwidget tr').appendTo($('#mutantwidget #seltable')); | |
$('#mw_optionstable').append("<tr><td onClick>2D Plot</td></tr>"); | $('#mw_optionstable').append("<tr><td onClick>2D Plot</td></tr>"); | ||
Line 201: | Line 268: | ||
{ | { | ||
$('#mw_optionstable').append("<tr><td>3D Plot</td></tr>"); | $('#mw_optionstable').append("<tr><td>3D Plot</td></tr>"); | ||
- | + | have_3d_data = true; | |
} | } | ||
- | + | // $('#mw_optionstable').append("<tr><td>Sequence</td></tr>"); | |
- | + | $('#mw_optionstable td').css({opacity:0.3}); | |
- | + | $('#mutantwidget').prepend('<div id="mw_grapharea"/>'); | |
- | + | $('#mw_grapharea').append('<div id="mw_plot"/>'); | |
- | + | $('#mw_grapharea').append('<div id="mw_3dplot"/>'); | |
+ | $('#mw_3dplot').append("<table id='navbuttons3d' style='position:absolute;bottom:0px;left:350px;'><tr><td><</td><td>></td></tr></table>") | ||
+ | $('#mw_3dplot #navbuttons3d td').css({width:'15px'}) | ||
+ | $('#mw_3dplot #navbuttons3d td').eq(0).mousedown(function(){theta -= Math.PI/8;rerender();}) | ||
+ | $('#mw_3dplot #navbuttons3d td').eq(1).mousedown(function(){theta += Math.PI/8;rerender();}) | ||
$('#mw_3dplot').toggle(); | $('#mw_3dplot').toggle(); | ||
- | + | $('#mutantwidget').parent().append('<div id="mw_sequencearea"/>'); | |
- | + | $('#mutantwidget span').hide(); | |
- | + | $('#mutantwidget .sequence').appendTo($('#mw_sequencearea')); | |
- | $('#mutantwidget').append("<div class='yaxis'>Relative | + | $('#mutantwidget').append("<div class='yaxis'>Relative Fluorescence</div>"); |
+ | $('#mutantwidget').append("<div class='xaxis'>Arabinose (wt%)</div>"); | ||
- | + | $('#mw_selectmenu td').mouseover(function() | |
- | + | { | |
- | + | if(!$(this).hasClass("selected")) | |
- | + | { | |
- | + | $(this).dequeue().animate({"opacity":1, "color":mutantcolors[$(this).parent().index()]}, 500); | |
- | + | } | |
- | + | }); | |
- | + | $('#mw_optionsmenu td').mouseover(function() | |
- | + | { | |
- | + | if(!$(this).hasClass("selected")) | |
- | + | { | |
- | + | $(this).dequeue().animate({"opacity":1, "color":selectedColor}, 500); | |
- | + | } | |
- | + | }); | |
- | + | $('#mw_optionsmenu td').mouseout(function() | |
- | + | { | |
- | + | if(!$(this).hasClass("selected")) | |
- | + | { | |
- | + | $(this).dequeue().animate({"opacity":.3, color:"rgb(225, 225, 225)"}, 500); | |
- | + | } | |
- | + | }); | |
- | + | $('#mw_selectmenu td').mouseout(function() | |
- | + | { | |
- | + | if(!$(this).hasClass("selected")) | |
- | + | { | |
- | + | $(this).dequeue().animate({"opacity":.3, color:"rgb(225, 225, 225)"}, 500); | |
- | + | } | |
- | + | }); | |
- | + | $('#mw_optionsmenu td').click( | |
- | + | function() { | |
- | + | menuitem = $(this).parent().index(); | |
- | + | if(!$(this).hasClass("selected")) | |
- | + | { | |
- | + | $('#mw_optionsmenu td').removeClass("selected"); | |
- | + | $(this).addClass("selected"); | |
- | + | $('#mw_optionsmenu td').mouseout(); | |
- | + | if($(this).text() == "2D Plot") | |
- | + | { | |
- | + | $('#mw_3dplot').hide(); | |
- | + | $('#mw_plot').show(); | |
- | + | $('.yaxis').show(); | |
- | + | $('.xaxis').show(); | |
- | + | widget_mode = "2D"; | |
- | + | dataseries = []; | |
- | + | $('#mw_selectmenu td').each( | |
- | + | function(index) | |
- | + | { | |
- | + | if($(this).hasClass("selected")) | |
- | + | { | |
- | + | if(data[index]) | |
- | + | { | |
- | + | dataseries.push(data[index]); | |
- | + | dataseries.push(errbars_2d[index]); | |
- | + | } | |
- | + | } | |
- | + | } | |
- | + | ); | |
- | + | if(!dataseries[0]) | |
- | + | { | |
- | + | dataseries.push([[0,0]]); | |
- | + | } | |
- | + | $.plot($("#mw_plot"), dataseries, | |
- | + | { | |
- | + | xaxis: {max:.014, min:0}, | |
- | + | yaxis: {max: 1.2, min:0}, | |
- | + | grid: { }, | |
- | + | points: {show: true}, | |
- | + | lines: {show: true} | |
- | + | }); | |
- | + | } | |
- | + | if($(this).text() == "3D Plot") | |
- | + | { | |
- | + | $('#mw_plot').hide(); | |
+ | $('#mw_3dplot').show(); | ||
+ | $('.yaxis').hide(); | ||
+ | $('.xaxis').hide(); | ||
+ | widget_mode = "3D"; | ||
+ | update3DPlotMeshes(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | ); | ||
$('#mw_optionsmenu td').eq(0).mouseover().click(); | $('#mw_optionsmenu td').eq(0).mouseover().click(); | ||
- | + | $('#mw_selectmenu td').click( | |
- | + | function() { | |
+ | if($(this).hasClass("selected")) | ||
+ | { | ||
+ | $(this).removeClass("selected"); | ||
+ | $(this).mouseout(); | ||
+ | $('#mw_sequencearea').children().eq($(this).parent().index()).hide(); | ||
+ | } else | ||
+ | { | ||
+ | $(this).dequeue().css({opacity:1}); | ||
+ | $(this).addClass("selected"); | ||
+ | $('#mw_sequencearea').children().hide(); | ||
+ | // $('#mw_sequencearea').children().eq($(this).parent().index()).show(); | ||
+ | } | ||
if(widget_mode == "2D") | if(widget_mode == "2D") | ||
{ | { | ||
- | + | dataseries = []; | |
- | + | $('#mw_selectmenu td').each( | |
- | + | function(index) | |
- | + | { | |
- | + | if($(this).hasClass("selected")) | |
- | + | { | |
- | + | if(data[index]) | |
- | + | { | |
- | + | dataseries.push(data[index]); | |
- | + | dataseries.push(errbars_2d[index]); | |
- | + | } | |
- | + | } | |
- | + | } | |
- | + | ); | |
- | + | if(!dataseries[0]) | |
- | + | { | |
- | + | dataseries.push([[0,0]]); | |
- | + | } | |
- | + | $.plot($("#mw_plot"), dataseries, | |
- | + | { | |
- | + | xaxis: {max:.014, min:0}, | |
- | + | yaxis: {max: 1.2, min:0}, | |
- | + | grid: { }, | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
points: {show: true}, | points: {show: true}, | ||
lines: {show: true} | lines: {show: true} | ||
- | + | }); | |
}else if(widget_mode == "3D") | }else if(widget_mode == "3D") | ||
{ | { | ||
- | + | update3DPlotMeshes(); | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
} | } | ||
- | + | } | |
- | + | ); | |
- | + | //Split sequences | |
- | + | $('#mutantwidget .sequence').each( | |
- | + | function(index) { | |
- | + | var curloc = 0; | |
- | + | var curseq = $(this).text(); | |
- | + | $(this).html(''); | |
- | + | while(curloc < curseq.length) | |
- | + | { | |
- | + | oldloc = curloc; | |
- | + | $(this).append(curseq.substr(oldloc, 15)).append(" "); | |
- | + | curloc += 10; | |
- | + | } | |
- | + | } | |
- | + | ); | |
- | + | //Extract plotting data | |
- | + | data = []; | |
- | + | errbars_2d = []; | |
- | + | $('#mutantwidget .xdata').each( | |
- | + | function(index) | |
- | + | { | |
- | + | data.push({color:mutantcolors[index], data:[]}); | |
- | + | errbars_2d.push({color:"#ff0000", data:[], points:{show:false}}); | |
- | + | var thisdatax = $(this).text().split(','); | |
- | + | var thisdatay = $('#mutantwidget .ydata').eq(index).text().split(','); | |
- | + | var thisdataerr = $('#mutantwidget .stdevs').eq(index).text().split(','); | |
- | + | var i; | |
- | + | for(i=0; i < thisdatay.length; ++i) | |
- | + | { | |
- | + | thisdatay[i] = parseFloat(thisdatay[i]); | |
- | + | thisdataerr[i] = parseFloat(thisdataerr[i]); | |
- | + | } | |
- | + | for(i=0; i < thisdatax.length; ++i) | |
- | + | { | |
- | } | + | thisdatax[i] = parseFloat(thisdatax[i]); |
- | + | data[index].data.push([thisdatax[i], thisdatay[i]]); | |
- | + | } | |
- | + | var errbarwidth = Math.max.apply(null,thisdatax)/150; | |
- | + | for(i=0; i < thisdatax.length; ++i) | |
- | + | { | |
- | + | errbars_2d[index].data.push([thisdatax[i], thisdatay[i]+thisdataerr[i]]); | |
- | + | errbars_2d[index].data.push([thisdatax[i], thisdatay[i]-thisdataerr[i]]); | |
+ | errbars_2d[index].data.push([null, null]); | ||
+ | errbars_2d[index].data.push([thisdatax[i]-errbarwidth, thisdatay[i]+thisdataerr[i]]); | ||
+ | errbars_2d[index].data.push([thisdatax[i]+errbarwidth, thisdatay[i]+thisdataerr[i]]); | ||
+ | errbars_2d[index].data.push([null, null]); | ||
+ | errbars_2d[index].data.push([thisdatax[i]-errbarwidth, thisdatay[i]-thisdataerr[i]]); | ||
+ | errbars_2d[index].data.push([thisdatax[i]+errbarwidth, thisdatay[i]-thisdataerr[i]]); | ||
+ | errbars_2d[index].data.push([null, null]); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | ); | ||
+ | $.plot($("#mw_plot"), [[0,0]], | ||
+ | { | ||
+ | xaxis: {max:.014, min:0}, | ||
+ | yaxis: {max: 1.2, min:0}, | ||
+ | grid: { }, | ||
+ | }); | ||
}); | }); | ||
sphereMaterial = new THREE.MeshBasicMaterial( | sphereMaterial = new THREE.MeshBasicMaterial( | ||
- | + | { | |
- | + | color:0xCC0000 | |
- | + | } | |
); | ); | ||
plotMaterial = new THREE.MeshFaceMaterial( | plotMaterial = new THREE.MeshFaceMaterial( | ||
- | // { | + | // { |
- | // | + | // color:0xCC0000, |
- | // | + | // opacity:.4, |
- | // | + | // vertexColors:true |
- | // } | + | // } |
); | ); | ||
pointMaterial = new THREE.ParticleCanvasMaterial( { color: 0xffffff, program: function(context) | pointMaterial = new THREE.ParticleCanvasMaterial( { color: 0xffffff, program: function(context) | ||
{ | { | ||
context.beginPath(); | context.beginPath(); | ||
- | + | context.arc( 0, 0, .5, 0, Math.PI * 2, true ); | |
- | + | context.fill(); | |
} } ); | } } ); | ||
axisMat = new THREE.LineBasicMaterial( | axisMat = new THREE.LineBasicMaterial( | ||
- | + | { | |
- | + | color:0xffffff, | |
- | + | opacity:1, | |
- | + | linewidth:1 | |
- | + | } | |
); | ); | ||
axisdimensions = [0, 5, 0, 0.0140, 0, 1]; | axisdimensions = [0, 5, 0, 0.0140, 0, 1]; | ||
Line 440: | Line 520: | ||
$(document).ready(function() { | $(document).ready(function() { | ||
- | + | data_3d = []; | |
- | + | errorbars_3d = []; | |
- | //Parse datas! | + | particles = []; |
- | + | meshchildren = []; | |
- | + | //Parse datas! | |
- | + | $('.zdata_3d').each( | |
- | + | function(index) | |
- | + | { | |
- | + | particles.push(new THREE.Geometry()); | |
+ | thisdataz = $(this).text().split(','); | ||
+ | thisdatax = $('.xdata_3d').eq(index).text().split(','); | ||
+ | thisdatay = $('.ydata_3d').eq(index).text().split(','); | ||
+ | thisdataerr = $('.stdevs_3d').eq(index).text().split(','); | ||
+ | |||
+ | |||
//numxpoints = thisdatax.length; | //numxpoints = thisdatax.length; | ||
//numypoints = thisdatay.length; | //numypoints = thisdatay.length; | ||
- | + | meshchildren.push(new THREE.Object3D()); | |
- | + | errorbars_3d.push(new THREE.Object3D()); | |
- | + | data_3d.push(new THREE.PlaneGeometry(100,100,numxpoints-1, numypoints-1)); | |
- | + | var i; | |
- | + | for(i=0; i < thisdatax.length; ++i) | |
- | + | { | |
- | + | thisdatax[i] = parseFloat(thisdatax[i]); | |
- | + | } | |
- | + | for(i=0; i < thisdatay.length; ++i) | |
- | + | { | |
- | + | thisdatay[i] = parseFloat(thisdatay[i]); | |
- | + | } | |
- | + | for(i=0; i < thisdataz.length; ++i) | |
- | var particle = new THREE.Vertex( | + | { |
- | new THREE.Vector3(thisdatax[i%thisdatax.length]/axisdimensions[1]*100, thisdatay[Math.floor(i/thisdatax.length)]*axisdimensions[3]*100, thisdataz[i]*axisdimensions[5]*100) | + | thisdataz[i] = parseFloat(thisdataz[i]); |
- | + | ||
- | + | /* | |
+ | var particle = new THREE.Vertex( | ||
+ | new THREE.Vector3(thisdatax[i%thisdatax.length]/axisdimensions[1]*100, | ||
+ | thisdatay[Math.floor(i/thisdatax.length)]/axisdimensions[3]*100, | ||
+ | thisdataz[i]/axisdimensions[5]*100) | ||
+ | ); | ||
+ | particles[index].vertices.push(particle); | ||
+ | var newparticle = new THREE.Particle(pointMaterial) | ||
+ | newparticle.position.x = particle.position.x; | ||
+ | newparticle.position.y = particle.position.y; | ||
+ | newparticle.position.z = particle.position.z; | ||
+ | meshchildren[index].addChild(newparticle); | ||
+ | */ | ||
+ | |||
+ | |||
+ | } | ||
+ | var lineMat = new THREE.LineBasicMaterial( | ||
+ | { | ||
+ | color:mutantcolors_hex[index], | ||
+ | opacity:1, | ||
+ | linewidth:2 | ||
+ | } | ||
+ | ); | ||
+ | for(i=0; i < thisdataerr.length; i++) | ||
+ | { | ||
+ | thisdataerr[i] = parseFloat(thisdataerr[i]); | ||
+ | var errbargeom = new THREE.Geometry(); | ||
+ | errbargeom.vertices.push(new THREE.Vertex(new THREE.Vector3( | ||
+ | thisdatax[i%thisdatax.length]/axisdimensions[1]*100, | ||
+ | thisdatay[Math.floor(i/thisdatax.length)]/axisdimensions[3]*100, | ||
+ | thisdataz[i]/axisdimensions[5]*100-thisdataerr[i]/axisdimensions[5]*100 | ||
+ | ))); | ||
+ | errbargeom.vertices.push(new THREE.Vertex(new THREE.Vector3( | ||
+ | thisdatax[i%thisdatax.length]/axisdimensions[1]*100, | ||
+ | thisdatay[Math.floor(i/thisdatax.length)]/axisdimensions[3]*100, | ||
+ | thisdataz[i]/axisdimensions[5]*100+thisdataerr[i]/axisdimensions[5]*100 | ||
+ | ))); | ||
+ | var errbar = new THREE.Line(errbargeom, lineMat); | ||
+ | errorbars_3d[index].addChild(errbar); | ||
+ | } | ||
+ | //Particles look like ass. | ||
+ | //Use lines instead. | ||
+ | |||
+ | for(i=0; i < thisdatax.length*(thisdatay.length-1); i++) | ||
+ | { | ||
+ | |||
+ | var linegeom = new THREE.Geometry(); | ||
+ | linegeom.vertices.push(new THREE.Vertex(new THREE.Vector3( | ||
+ | thisdatax[i%thisdatax.length]/axisdimensions[1]*100, | ||
+ | thisdatay[Math.floor(i/thisdatax.length)]/axisdimensions[3]*100, | ||
+ | thisdataz[i]/axisdimensions[5]*100 | ||
+ | ))); | ||
+ | linegeom.vertices.push(new THREE.Vertex(new THREE.Vector3( | ||
+ | thisdatax[(i+thisdatax.length)%thisdatax.length]/axisdimensions[1]*100, | ||
+ | thisdatay[Math.floor((i+thisdatax.length)/thisdatax.length)]/axisdimensions[3]*100, | ||
+ | thisdataz[i+thisdatax.length]/axisdimensions[5]*100 | ||
+ | ))); | ||
+ | meshchildren[index].addChild(new THREE.Line(linegeom, lineMat)); | ||
+ | } | ||
+ | for(i=0; i < (thisdatax.length-1)*(thisdatay.length); i++) | ||
+ | { | ||
+ | //Particles look like ass. | ||
+ | //Use lines instead. | ||
+ | var linegeom = new THREE.Geometry(); | ||
+ | linegeom.vertices.push(new THREE.Vertex(new THREE.Vector3( | ||
+ | thisdatax[i%(thisdatax.length-1)]/axisdimensions[1]*100, | ||
+ | thisdatay[Math.floor(i/(thisdatax.length-1))]/axisdimensions[3]*100, | ||
+ | thisdataz[Math.floor(i/(thisdatax.length-1))+i]/axisdimensions[5]*100 | ||
+ | ))); | ||
+ | linegeom.vertices.push(new THREE.Vertex(new THREE.Vector3( | ||
+ | thisdatax[i%(thisdatax.length-1)+1]/axisdimensions[1]*100, | ||
+ | thisdatay[Math.floor(i/(thisdatax.length-1))]/axisdimensions[3]*100, | ||
+ | thisdataz[Math.floor(i/(thisdatax.length-1))+i+1]/axisdimensions[5]*100 | ||
+ | ))); | ||
+ | meshchildren[index].addChild(new THREE.Line(linegeom, lineMat)); | ||
+ | } | ||
+ | |||
+ | for(i=0; i < numxpoints; ++i) | ||
+ | { | ||
+ | for(var j=0; j < numypoints; ++j) | ||
+ | { | ||
+ | var thisx = thisdatax[thisdatax.length-1]*i/(numxpoints-1); | ||
+ | var thisy = thisdatay[thisdatay.length-1]*j/(numypoints-1); | ||
+ | data_3d[index].vertices[j*numxpoints+i].position.x = thisx/axisdimensions[1]*100; | ||
+ | data_3d[index].vertices[j*numxpoints+i].position.y = thisy/axisdimensions[3]*100; | ||
+ | //Find flanking x,y values | ||
+ | var kx = ky = 0; | ||
+ | while(thisx >= thisdatax[kx]) { | ||
+ | kx=kx+1; | ||
+ | } | ||
+ | while(thisy >= thisdatay[ky]) { | ||
+ | ky=ky+1; | ||
+ | } | ||
+ | if(kx > thisdatax.length-1) | ||
+ | { | ||
+ | kx = thisdatax.length-1; | ||
+ | } | ||
+ | if(ky > thisdatay.length-1) | ||
+ | { | ||
+ | ky = thisdatay.length-1; | ||
+ | } | ||
+ | kx--; | ||
+ | ky--; | ||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
- | |||
kx = parseInt(kx); | kx = parseInt(kx); | ||
ky = parseInt(ky); | ky = parseInt(ky); | ||
Line 499: | Line 667: | ||
alert("Porblem!\nkx:" + kx + "\nky:" + ky + "\nkx is a "+typeof(kx) + "\nky is a" +typeof(ky) + "\nset:" + index); | alert("Porblem!\nkx:" + kx + "\nky:" + ky + "\nkx is a "+typeof(kx) + "\nky is a" +typeof(ky) + "\nset:" + index); | ||
} | } | ||
- | + | thisz = interp2(thisdatax[kx], | |
- | + | thisdatay[ky], | |
- | + | thisdatax[kx+1], | |
- | + | thisdatay[ky+1], | |
- | + | thisdataz[tli], | |
- | + | thisdataz[tri], | |
- | + | thisdataz[bli], | |
- | + | thisdataz[bri], thisx, thisy) | |
- | + | data_3d[index].vertices[j*numxpoints+i].position.z = thisz/axisdimensions[5]*100; | |
- | + | } | |
- | + | } | |
- | + | data_3d[index].computeCentroids(); | |
- | + | //vertex colors | |
/* | /* | ||
- | + | var colors = []; | |
- | + | for(i=0; i < thisdataz.length; ++i) | |
- | + | { | |
- | + | var color = new THREE.Color(0x550000); | |
- | // | + | // color.setHSV(.125, 1, 0); |
- | + | colors.push(color); | |
- | + | } | |
*/ | */ | ||
- | + | materials = []; | |
- | + | for(i=0; i < data_3d[index].faces.length; ++i) | |
- | + | { | |
- | + | thisfacecolor = ( | |
- | + | data_3d[index].vertices[data_3d[index].faces[i].a].position.z+ | |
- | + | data_3d[index].vertices[data_3d[index].faces[i].b].position.z+ | |
- | + | data_3d[index].vertices[data_3d[index].faces[i].c].position.z+ | |
- | + | data_3d[index].vertices[data_3d[index].faces[i].d].position.z)/4/100; | |
- | + | materials.push([new THREE.MeshBasicMaterial( | |
- | + | { | |
- | + | color:thisfacecolor*0xffffff, | |
- | + | opacity:.6 | |
- | + | } | |
- | + | )]); | |
if(!thisfacecolor) | if(!thisfacecolor) | ||
{ | { | ||
alert("Something is terribly wrong!\na ("+data_3d[index].faces[i].a+"):"+data_3d[index].vertices[data_3d[index].faces[i].a].position.z+"\nb("+data_3d[index].faces[i].b+"):"+data_3d[index].vertices[data_3d[index].faces[i].b].position.z+"\nc("+data_3d[index].faces[i].c+"):"+data_3d[index].vertices[data_3d[index].faces[i].c].position.z+"\nd("+data_3d[index].faces[i].d+"):"+data_3d[index].vertices[data_3d[index].faces[i].a].position.z); | alert("Something is terribly wrong!\na ("+data_3d[index].faces[i].a+"):"+data_3d[index].vertices[data_3d[index].faces[i].a].position.z+"\nb("+data_3d[index].faces[i].b+"):"+data_3d[index].vertices[data_3d[index].faces[i].b].position.z+"\nc("+data_3d[index].faces[i].c+"):"+data_3d[index].vertices[data_3d[index].faces[i].c].position.z+"\nd("+data_3d[index].faces[i].d+"):"+data_3d[index].vertices[data_3d[index].faces[i].a].position.z); | ||
} | } | ||
- | + | var newcolor = colorRamp(thisfacecolor, cool_color_ramp); | |
- | + | materials[i][0].color.setRGB(newcolor[0], newcolor[1], newcolor[2]); | |
- | + | data_3d[index].faces[i].materials = materials[i]; | |
- | + | } | |
- | + | ||
- | + | } | |
- | + | ); | |
- | + | var origin = new THREE.Vertex(new THREE.Vector3(0,0,0)); | |
- | + | ||
- | + | theta = -Math.PI/4; | |
- | + | phi = Math.PI/8; | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | //Axis labels | |
- | + | var x = document.createElement("canvas"); | |
- | + | var xc = x.getContext("2d"); | |
- | + | x.width = 400; | |
+ | x.height = 40; | ||
+ | xc.fillStyle = "#ffffff"; | ||
+ | xc.font = "20pt arial"; | ||
+ | xc.textBaseline = "top"; | ||
+ | xc.fillText("IPTG (mM)", 10, 0); | ||
- | + | var xm = new THREE.MeshBasicMaterial({ | |
- | + | map: new THREE.Texture(x) | |
- | + | }); | |
- | + | xm.map.needsUpdate = true; | |
+ | |||
+ | xaxislabel = new THREE.Mesh(new THREE.PlaneGeometry(400, 40, 2, 2), xm); | ||
+ | xaxislabel.position.x = -50; | ||
+ | xaxislabel.position.y = 0; | ||
+ | xaxislabel.position.z = -48; | ||
xaxislabel.scale.x = 0.2; | xaxislabel.scale.x = 0.2; | ||
xaxislabel.scale.y = -0.2; | xaxislabel.scale.y = -0.2; | ||
- | + | xaxislabel.rotation.x = -Math.PI/2; | |
+ | xaxislabel.rotation.y = -Math.PI/2; | ||
+ | xaxislabel.doubleSided = true; | ||
- | + | var x = document.createElement("canvas"); | |
- | + | var xc = x.getContext("2d"); | |
- | + | x.width = 400; | |
- | + | x.height = 40; | |
- | + | xc.fillStyle = "#ffffff"; | |
- | + | xc.font = "20pt arial"; | |
- | + | xc.textBaseline = "top"; | |
- | + | xc.fillText("Arabinose (wt%)", 10, 0); | |
- | + | var xm = new THREE.MeshBasicMaterial({ | |
- | + | map: new THREE.Texture(x) | |
- | + | }); | |
- | + | xm.map.needsUpdate = true; | |
- | + | yaxislabel = new THREE.Mesh(new THREE.PlaneGeometry(400, 40, 2, 2), xm); | |
- | + | yaxislabel.position.x = 0; | |
- | + | yaxislabel.position.y = -50; | |
- | + | yaxislabel.position.z = -48; | |
yaxislabel.scale.x = 0.2; | yaxislabel.scale.x = 0.2; | ||
yaxislabel.scale.y = -0.2; | yaxislabel.scale.y = -0.2; | ||
- | + | yaxislabel.rotation.x = -Math.PI/2; | |
+ | yaxislabel.doubleSided = true; | ||
- | + | var x = document.createElement("canvas"); | |
- | + | var xc = x.getContext("2d"); | |
- | + | x.width = 400; | |
- | + | x.height = 40; | |
- | + | xc.fillStyle = "#ffffff"; | |
- | + | xc.font = "20pt arial"; | |
- | + | xc.textBaseline = "top"; | |
- | + | xc.fillText("Relative Fluorescence", 10, 0); | |
- | + | var xm = new THREE.MeshBasicMaterial({ | |
- | + | map: new THREE.Texture(x) | |
- | + | }); | |
- | + | xm.map.needsUpdate = true; | |
- | + | zaxislabel = new THREE.Mesh(new THREE.PlaneGeometry(400, 40, 2, 2), xm); | |
- | + | zaxislabel.position.x = -50; | |
- | + | zaxislabel.position.y = -52; | |
- | + | zaxislabel.position.z = 0; | |
+ | zaxislabel.rotation.x = -Math.PI/2; | ||
+ | zaxislabel.rotation.y = -Math.PI/2; | ||
+ | zaxislabel.rotation.z = -Math.PI/2; | ||
zaxislabel.scale.x = 0.2; | zaxislabel.scale.x = 0.2; | ||
zaxislabel.scale.y = -0.2; | zaxislabel.scale.y = -0.2; | ||
- | |||
- | + | zaxislabel.doubleSided = true; | |
- | + | zaxislabel.updateMatrix(); | |
- | + | var $container = $('#mw_3dplot'); | |
- | + | $('body').mouseup(function(){ | |
- | + | isdragging = false; | |
- | + | $container.unbind('mousemove'); | |
- | + | }); | |
- | + | $container.mousedown(function(event){ | |
- | + | isdragging = true; | |
- | + | lastMouseX = event.pageX; | |
- | + | lastMouseY = event.pageY; | |
- | + | $container.mousemove(function(event) | |
- | + | { | |
- | + | theta += (lastMouseX - event.pageX)/70 | |
- | + | phi -= (lastMouseY - event.pageY)/70; | |
- | + | lastMouseX = event.pageX; | |
- | + | lastMouseY = event.pageY; | |
- | + | rerender(); | |
- | + | }); | |
- | + | }); | |
- | + | renderer = new THREE.CanvasRenderer(); | |
- | + | //renderer.autoClear = false; | |
- | + | camera = new THREE.OrthoCamera( -75, 75, 75, -75, - 2000, 1000 ); | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | scene = new THREE.Scene(); | |
- | + | camera.position.x = 250; | |
- | + | camera.position.y = -150; | |
- | + | camera.position.z = 75; | |
- | + | camera.up.y = 0; | |
- | + | camera.up.z = 1; | |
- | + | // camera.rotation.y = -Math.PI/6; | |
+ | camera.position.x = 250*Math.cos(theta); | ||
+ | camera.position.y = 250*Math.sin(theta); | ||
+ | renderer.setSize(WIDTH, HEIGHT); | ||
+ | $container.append(renderer.domElement); | ||
+ | var radius = 50, segments = 16, rings = 16; | ||
- | + | sphere = new THREE.Mesh( | |
- | + | new THREE.SphereGeometry(radius, | |
- | + | segments, | |
- | + | rings), | |
- | + | sphereMaterial | |
- | + | ); | |
- | + | sphere.position.x = 50; | |
- | + | sphere.position.y = 50; | |
- | + | sphere.position.z = 50; | |
- | + | ||
- | + | ||
- | + | ||
// add it to the scene | // add it to the scene | ||
- | + | plot_mesh = []; | |
+ | plot_points = []; | ||
for(var i = 0; i < data_3d.length; ++i) | for(var i = 0; i < data_3d.length; ++i) | ||
{ | { | ||
plot_mesh.push(new THREE.Mesh(data_3d[i], plotMaterial)); | plot_mesh.push(new THREE.Mesh(data_3d[i], plotMaterial)); | ||
plot_mesh[i].doubleSided = true; | plot_mesh[i].doubleSided = true; | ||
+ | |||
+ | plot_points.push(new THREE.ParticleSystem( | ||
+ | particles[i], | ||
+ | pointMaterial)); | ||
} | } | ||
+ | |||
plot_obj = new THREE.Object3D(); | plot_obj = new THREE.Object3D(); | ||
+ | plot_obj.rotation.z = -Math.PI/2; | ||
+ | plot_obj.scale.x = -1; | ||
//plot_mesh.addChild(sphere); | //plot_mesh.addChild(sphere); | ||
- | |||
- | + | axisgeom = new THREE.Geometry(); | |
- | + | axisgeom.vertices.push(origin); | |
- | + | axisgeom.vertices.push(new THREE.Vertex(new THREE.Vector3(100,0,0))); | |
- | + | axisgeom.vertices.push(new THREE.Vertex(new THREE.Vector3(98, 1, 0))); | |
- | + | axisgeom.vertices.push(new THREE.Vertex(new THREE.Vector3(98, -1, 0))); | |
- | + | axisgeom.vertices.push(new THREE.Vertex(new THREE.Vector3(100, 0, 0))); | |
+ | |||
+ | xaxis = new THREE.Line( | ||
+ | axisgeom, | ||
+ | axisMat | ||
+ | ); | ||
- | + | yaxis = new THREE.Line( | |
- | + | axisgeom, | |
- | + | axisMat | |
- | + | ); | |
+ | yaxis.rotation.z = 90*Math.PI/180; | ||
- | + | zaxis = new THREE.Line( | |
- | + | axisgeom, | |
- | + | axisMat | |
- | + | ); | |
- | + | scene.addChild(xaxislabel); | |
+ | scene.addChild(yaxislabel); | ||
+ | scene.addChild(zaxislabel); | ||
- | + | zaxis.rotation.y = -90*Math.PI/180; | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | plot_obj.position.x = -50; | |
- | + | plot_obj.position.z = -50; | |
- | + | plot_obj.position.y = -50; | |
- | + | zaxis.position.x = -50; | |
- | + | zaxis.position.z = -50; | |
- | + | zaxis.position.y = -50; | |
- | + | xaxis.position.x = -50; | |
- | + | xaxis.position.z = -50; | |
- | + | xaxis.position.y = -50; | |
- | + | yaxis.position.x = -50; | |
- | + | yaxis.position.z = -50; | |
- | + | yaxis.position.y = -50; | |
- | |||
- | |||
- | |||
- | |||
//plot_obj.addChild(particleSystem); | //plot_obj.addChild(particleSystem); | ||
- | |||
- | |||
- | |||
- | + | scene.addChild(xaxis); | |
+ | scene.addChild(yaxis); | ||
+ | scene.addChild(zaxis); | ||
+ | scene.addChild(plot_obj); | ||
+ | // origin_object.addChild(sphere); | ||
- | + | ||
- | + | //Grid | |
- | + | var gridlinegeom = new THREE.Geometry(); | |
- | // | + | gridlinegeom.vertices.push(new THREE.Vertex(new THREE.Vector3(0,0,0))); |
- | + | gridlinegeom.vertices.push(new THREE.Vertex(new THREE.Vector3(100,0,0))); | |
- | renderer.render(scene, camera); | + | |
+ | for(var i=1; i <= 5; i++) | ||
+ | { | ||
+ | var gridline = new THREE.Line(gridlinegeom, axisMat); | ||
+ | gridline.position.y = i/5*100-50; | ||
+ | gridline.position.x = -50; | ||
+ | gridline.position.z = -50; | ||
+ | scene.addChild(gridline); | ||
+ | |||
+ | |||
+ | |||
+ | var gridline = new THREE.Line(gridlinegeom, axisMat); | ||
+ | gridline.position.x = i/5*100-50; | ||
+ | gridline.position.y = -50; | ||
+ | gridline.position.z = -50; | ||
+ | gridline.rotation.z = Math.PI/2; | ||
+ | scene.addChild(gridline); | ||
+ | } | ||
+ | yticklabels = []; | ||
+ | xticklabels = []; | ||
+ | for(var i=1; i <= 5; i++) | ||
+ | { | ||
+ | var x = document.createElement("canvas"); | ||
+ | var xc = x.getContext("2d"); | ||
+ | x.width = 40; | ||
+ | x.height = 40; | ||
+ | xc.fillStyle = "#ffffff"; | ||
+ | xc.font = "12pt arial"; | ||
+ | xc.textBaseline = "top"; | ||
+ | xc.fillText(i/5*axisdimensions[1], 10, 0); | ||
+ | |||
+ | var xm = new THREE.MeshBasicMaterial({ | ||
+ | map: new THREE.Texture(x) | ||
+ | }); | ||
+ | xm.map.needsUpdate = true; | ||
+ | var xtick = new THREE.Mesh(new THREE.PlaneGeometry(13/ASPECT, 13, 2, 2), xm); | ||
+ | xtick.position.y = i/5*100-50; | ||
+ | xtick.position.x = -50; | ||
+ | xtick.position.z = -58; | ||
+ | xtick.rotation.x = Math.PI/2; | ||
+ | xtick.doubleSided = true; | ||
+ | xtick.updateMatrix(); | ||
+ | scene.addChild(xtick); | ||
+ | |||
+ | var x = document.createElement("canvas"); | ||
+ | var xc = x.getContext("2d"); | ||
+ | x.width = 80; | ||
+ | x.height = 40; | ||
+ | xc.fillStyle = "#ffffff"; | ||
+ | xc.font = "12pt arial"; | ||
+ | xc.textBaseline = "top"; | ||
+ | xc.fillText((i/5*axisdimensions[3]).toFixed(4), 10, 0); | ||
+ | |||
+ | var xm = new THREE.MeshBasicMaterial({ | ||
+ | map: new THREE.Texture(x) | ||
+ | }); | ||
+ | xm.map.needsUpdate = true; | ||
+ | var ytick = new THREE.Mesh(new THREE.PlaneGeometry(26/ASPECT, 13, 2, 2), xm); | ||
+ | ytick.position.x = i/5*100-50; | ||
+ | ytick.position.y = -50; | ||
+ | ytick.position.z = -58; | ||
+ | ytick.rotation.x = Math.PI/2; | ||
+ | ytick.doubleSided = true; | ||
+ | ytick.updateMatrix(); | ||
+ | scene.addChild(ytick); | ||
+ | |||
+ | xticklabels.push(xtick); | ||
+ | yticklabels.push(ytick); | ||
+ | } | ||
+ | |||
+ | var particle = new THREE.Particle(pointMaterial); | ||
+ | |||
+ | |||
+ | renderer.render(scene, camera); | ||
Line 830: | Line 1,081: | ||
-ms-transform: rotate(-90deg); | -ms-transform: rotate(-90deg); | ||
top:179px; | top:179px; | ||
- | left:- | + | left:-40px; |
+ | position:absolute; | ||
+ | } | ||
+ | |||
+ | .xaxis { | ||
+ | bottom:15px; | ||
position:absolute; | position:absolute; | ||
+ | left:320px; | ||
} | } | ||
</style> | </style> | ||
</html> | </html> |
Latest revision as of 03:39, 29 September 2011