Template:Team:Valencia Biocampus/Templates/js/simuelegans2.js
From 2013.igem.org
Line 412: | Line 412: | ||
circle.remove(); | circle.remove(); | ||
c_elegans.remove(); | c_elegans.remove(); | ||
- | if(path1 !== 'undefined'){ | + | if(typeof path1 !== 'undefined'){ |
path1.remove(); | path1.remove(); | ||
path_in_coords.length = 0; | path_in_coords.length = 0; |
Latest revision as of 09:55, 30 September 2013
Raphael.fn.arrow = function(x1, y1, x2, y2, size) { var angle = Raphael.angle(x1, y1, x2, y2); var a45 = Raphael.rad(angle-45); var a45m = Raphael.rad(angle+45); var a135 = Raphael.rad(angle-135); var a135m = Raphael.rad(angle+135); var x1a = x1 + Math.cos(a135) * size; var y1a = y1 + Math.sin(a135) * size; var x1b = x1 + Math.cos(a135m) * size; var y1b = y1 + Math.sin(a135m) * size; var x2a = x2 + Math.cos(a45) * size; var y2a = y2 + Math.sin(a45) * size; var x2b = x2 + Math.cos(a45m) * size; var y2b = y2 + Math.sin(a45m) * size; return this.path( "M"+x1+" "+y1+"L"+x1a+" "+y1a+ "M"+x1+" "+y1+"L"+x1b+" "+y1b+ "M"+x1+" "+y1+"L"+x2+" "+y2+ "M"+x2+" "+y2+"L"+x2a+" "+y2a+ "M"+x2+" "+y2+"L"+x2b+" "+y2b ); };
simuelegans = function() {};
var initialx = -1; var initialy = -1;
var initialr; var initiala;
var canvas = Raphael("raphael", 500, 500); // Back canvas (contains the drawing)
var path_in_coords = new Array();
function xytopath(x, y){
var guide_path, path, full_path;
if(initialx==-1 && initialy==-1){ initialx = 0; initialy = 0; }
var path2return = new Array(x.length);
var tmpx, tmpy;
tmpx = (x[0] * plate.attrs.r / simulator.plate_radius + plate.attrs.cx); tmpy = (y[0] * plate.attrs.r / simulator.plate_radius + plate.attrs.cy);
path2return[-1] = "[\"M"+tmpx+","+tmpy+"\"";
for(var i =1; i<x.length ; i++){
tmpx = (x[i-1] * plate.attrs.r / simulator.plate_radius + plate.attrs.cx); tmpy = (y[i-1] * plate.attrs.r / simulator.plate_radius + plate.attrs.cy);
path2return[i-1] = "[\"M"+tmpx+","+tmpy+"\", ";
tmpx = (x[i] * plate.attrs.r / simulator.plate_radius + plate.attrs.cx); tmpy = (y[i] * plate.attrs.r / simulator.plate_radius + plate.attrs.cy);
path2return[i-1] += "\"L"+tmpx+","+tmpy+"\" ]";
path_in_coords.push({x: tmpx, y: tmpy});
}
return path2return;
}
function Attractant(Xpx, Ypx){ this.Xpx = Xpx; this.Ypx = Ypx;
this.R = (Math.sqrt( (Xpx - plate.attrs.cx )*(Xpx - plate.attrs.cx ) + (Ypx - plate.attrs.cy)*(Ypx - plate.attrs.cy ) ) / plate.attrs.r) * simulator.plate_radius;
this.A = Math.atan2(Ypx - plate.attrs.cy, Xpx - plate.attrs.cx)
this.x = this.R * Math.cos(this.A); // x on the plate
this.y = this.R * Math.sin(this.A); // y on the plate
}
simuelegans.RandNorm = function(m, s){
this.mean = m; this.stdDev = s; this.isSpareReady = false; this.spare = 0; this.valuern = 0; }
simuelegans.RandNorm.prototype.getRandNorm = function() { if (this.isSpareReady) { this.isSpareReady = false; this.valuern = this.spare * this.stdDev + this.mean; } else { var u, v, s; do { u = Math.random() * 2 - 1; v = Math.random() * 2 - 1; s = u * u + v * v; } while (s >= 1 || s == 0); var mul = Math.sqrt(-2.0 * Math.log(s) / s); this.spare = v * mul; this.isSpareReady = true; this.valuern = this.mean + this.stdDev * u * mul; } return this.valuern; }; simuelegans.RandNorm = function(m, s){
this.mean = m; this.stdDev = s; this.isSpareReady = false; this.spare = 0; this.valuern = 0; }
simuelegans.RandNorm.prototype.getRandNorm = function() { if (this.isSpareReady) { this.isSpareReady = false; this.valuern = this.spare * this.stdDev + this.mean; } else { var u, v, s; do { u = Math.random() * 2 - 1; v = Math.random() * 2 - 1; s = u * u + v * v; } while (s >= 1 || s == 0); var mul = Math.sqrt(-2.0 * Math.log(s) / s); this.spare = v * mul; this.isSpareReady = true; this.valuern = this.mean + this.stdDev * u * mul; } return this.valuern; };
simuelegans.Chemotaxis = function(h, t, r0, a0){
this.tmax = t; this.h = h; a0 *= Math.PI / 180.0; this.x0 = r0 * Math.cos(a0); this.y0 = r0 * Math.sin(a0); this.tsize = this.tmax / h; this.x = new Array(this.tsize); this.y = new Array(this.tsize); this.c = new Array(this.tsize); this.dc = new Array(this.tsize); this.v = new Array(this.tsize); this.g = new Array(this.tsize); this.dg = new Array(this.tsize); this.d = new Array(this.tsize); this.temp = new Array(this.tsize);
this.attractants = new Array(); // array list of Attractant objects
}
simuelegans.Chemotaxis.prototype.addAttractant = function(attractant) {
this.attractants.push(attractant); } simuelegans.Chemotaxis.prototype.correctionFactor = function(dc) { if (dc < 0) { return 1.5 - Math.exp(11.2536 * dc); } else { return 0.5; } } // x0, y0 --> attractant coords // x, y --> where is calculated simuelegans.Chemotaxis.prototype.attractantDiffusion = function(x0, y0, x, y) {
var t1 = 19 * 3600; var t2 = 4.5 * 3600; var N0 = 500; var de = 0.264; var D = 1.861e-5; var temp = 1;
return N0 * (Math.exp(-((x-x0)*(x-x0) + (y-y0)*(y-y0)) / 4 * D * (temp + t1)) / (4 * Math.PI * de * D * (temp + t1)) + Math.exp(-((x-x0)*(x-x0) + (y-y0)*(y-y0)) / 4 * D * (temp + t2)) / (4 * Math.PI * de * D * (temp + t2)) );
};
simuelegans.Chemotaxis.prototype.simulate = function(r0, a0) { this.x0 = r0 * Math.cos(a0); this.y0 = r0 * Math.sin(a0); this.x[0] = this.x0; this.y[0] = this.y0; this.temp[0] = 0;
this.c[0] = 0; for (var i in this.attractants) { this.c[0] += this.attractantDiffusion(this.attractants[i].x, this.attractants[i].y, this.x0, this.y0); };
this.dc[0] = 0; this.v[0] = 0;
this.g[0] = 2 * Math.PI * Math.random(); this.dg[0] = 0;
var rnd1 = new simuelegans.RandNorm(0.0152, 0.00702); var rnd2 = new simuelegans.RandNorm(0.861 * Math.PI / 180, 38.9 * Math.PI / 180); var rnd3 = new simuelegans.RandNorm(0.441 * Math.PI / 180, 2.12 * Math.PI / 180);
this.d[0] = rnd3.getRandNorm();
for (var i = 0; i < this.tsize - 1; i++) { this.temp[i + 1] = this.h * i; this.x[i + 1] = this.x[0] - 0.01; this.y[i + 1] = this.y[0] - 0.01; this.v[i + 1] = 0.01;
do { this.c[i+1] = 0; for (var j in this.attractants) { this.c[i+1] += this.attractantDiffusion(this.attractants[j].x, this.attractants[j].y, this.x[i], this.y[i]); };
this.dc[i + 1] = (this.c[i + 1] - this.c[i]) / this.h;
this.v[i + 1] = rnd1.getRandNorm(); var cf = this.correctionFactor(this.dc[i + 1]); this.dg[i + 1] = rnd2.getRandNorm() * cf; this.d[i + 1] = rnd3.getRandNorm(); var l = this.h * this.v[i + 1]; this.g[i + 1] = this.h * (this.dg[i + 1] + this.d[i + 1]) + this.g[i]; this.x[i + 1] = l * Math.cos(this.g[i + 1]) + this.x[i]; this.y[i + 1] = l * Math.sin(this.g[i + 1]) + this.y[i];
} while ((Math.sqrt(this.x[i + 1] * this.x[i + 1] + this.y[i + 1] * this.y[i + 1]) > simulator.plate_radius)); } }
var strpath;
var path1;
var pathcolor = {stroke : "#5a7881"};
var plate;
var circle; var arrow_radius; var arrow_title;
var c_elegans;
var attractant; var attractantX, attractantY; var attractantsArray = new Array();
var gui = new dat.GUI({ autoPlace: false }); var customContainer = document.getElementById('simuelegans_gui'); customContainer.appendChild(gui.domElement);
function simulator(){
this.plate_radius = 4; this.simulation_length = 2000; this.duration = 50; this.initSimulation = function() { simndraw(circle.attrs.cx, circle.attrs.cy);
circle.toFront(); // C.elegans circle c_elegans.toFront();
plate.toFront(); };
}
var simulator = new simulator();
gui.add(simulator, 'plate_radius', 0.8, 4.5).name("Plate radius (cm)"); gui.add(simulator, 'simulation_length', 200, 4000).name("Duration "); gui.add(simulator, 'initSimulation').name("Init animation");
function initPlate(){
plate = canvas.circle(250, 250, 230); plate.attr("stroke", "#cac0b0"); plate.attr("fill", "#cac0b0"); plate.attr("fill-opacity", "0"); // fill with opacity 0 to be clickable plate.attr("cursor", "crosshair"); plate.click(onclickplate); plate.node.oncontextmenu = function(e){
attractantX = e.clientX - $("#raphael").offset().left; attractantY = e.clientY - $("#raphael").offset().top; attractant = new Attractant(attractantX, attractantY); // x & y in px
canvas.circle(attractant.Xpx, attractant.Ypx, 30).attr("fill","rgba(225,217,30,0.25)").attr("stroke", "rgba(200,199,10,0.55)");
attractantsArray.push(attractant); return false;
}
arrow_radius = canvas.arrow(250, 493, 470, 493, 10); arrow_title = canvas.text(360, 487, "Radius: "+simulator.plate_radius.toFixed(1)+"cm").attr({fill: '#000'});
}
function initCircle(x, y){
circle = canvas.circle(x, y, 3); circle.attr("stroke-width", 1); circle.attr("stroke", "#f00"); circle.attr("fill", "#f00");
//c_elegans = canvas.image("http://www.tonnyesp.com/igem/elegans.png", x - 120/7/2, y - 120/7/2, 120/7, 74/7); c_elegans = canvas.circle(x, y, 3); c_elegans.attr("stroke-width", 1); c_elegans.attr("stroke", "#5a7881");
}
function animateCircle(step, strpath){
if(step <= strpath.length){
path1 = canvas.path(strpath[step]).attr( { stroke: "#5a7881", fill: "none" });
//c_elegans.attr({guide : path1, along : 1}).animate({along : 0}, 50, "linear"); //c_elegans.attr({along: 0});
//c_elegans.rotate(Math.atan2(c_elegans.attrs.y, c_elegans.attrs.x))
c_elegans.animate({ cx: path_in_coords[step+1].x, cy: path_in_coords[step+1].y}, 50);
path1.animate({path: strpath[step+1]}, 50, function(){ animateCircle(step+1, strpath); }) }
}
function simndraw(x, y){
initialx = x ; initialy = y;
initialr = (Math.sqrt( (initialx - plate.attrs.cx )*(initialx - plate.attrs.cx ) + (initialy - plate.attrs.cy)*(initialy - plate.attrs.cy ) ) / plate.attrs.r) * simulator.plate_radius;
initiala = Math.atan2(initialy - plate.attrs.cy, initialx - plate.attrs.cx)
//chemotaxis.attractants.length = 0;
chemotaxis = new simuelegans.Chemotaxis(1.0, simulator.simulation_length.toFixed(), initialr, initiala);
for(var i in attractantsArray){ chemotaxis.addAttractant(attractantsArray[i]); }
chemotaxis.simulate(initialr, initiala);
strpath = xytopath(chemotaxis.x, chemotaxis.y);
animateCircle(-1, strpath);
}
var x0, y0;
initPlate();
initCircle(plate.attrs.cx, plate.attrs.cy);
//simndraw(plate.attrs.cx, plate.attrs.cy);
var chemotaxis;
function onclickplate(e) {
circle.remove(); c_elegans.remove(); if(typeof path1 !== 'undefined'){ path1.remove(); path_in_coords.length = 0; } canvas.clear();
initPlate();
x0 = e.clientX - $("#raphael").offset().left; y0 = e.clientY - $("#raphael").offset().top;
initCircle(x0, y0); // C.elegans starting position circle.toFront(); // C.elegans circle
//simndraw(x0, y0); // simulates and loads data, and then starts animation
};