htmol
Version:
NEXT-GENERATION MOLECULAR DYNAMICS WEB VISUALIZATION
499 lines (443 loc) • 15.3 kB
JavaScript
/*
This file is part of HTMoL:
Copyright (C) 2014 Dr. Mauricio Carrillo-Tripp
http://tripplab.com
Developers:
v1.0 Leonardo Alvarez-Rivera, Francisco Javier Becerra-Toledo, Adan Vega-Ramirez
v2.0 Javier Garcia-Vieyra
v3.0 Omar Israel Lara-Ramirez, Eduardo González-Zavala, Emmanuel Quijas-Valades, Julio Cesar González-Vázquez
v3.5 Leonardo Alvarez-Rivera
*/
var contBonds=0;
var contBS=0;
var LstAtSelec=[];
var CzPers;
function Aminoacid(number,name,state)
{
this.Number=number;
this.Name=name;
this.State=state;
this.LstAtoms=[];
this.Type=null;
this.GetAtoms=function()
{
return this.LstAtoms;
}
}
function Chain(name,state)
{
this.Name=name;
this.State=state;
this.LstAminoAcid=[];
this.LstSkeleton=[];
this.GetSkeleton=function()
{
return this.LstSkeleton;
}
this.GetAminoacid=function()
{
return this.LstAminoAcid;
}
}
function Bond()
{
this.LstAtoms=[];
this.id=0;
this.State=null; ////////////////////////////////////////////////////////////////////////
this.BPosition=null; //es para saber en qué posición del arreglo se encuentra esta línea
}
function BondSkeleton()
{
this.id=0;
this.LstAtoms=[];
}
function Molecule()
{
this.Name='';
this.LstChain=[];
this.LstAtoms=[];
this.LstBonds=[];
this.LstBondsSkeleton=[];
this.LstHelixAndSheet=[];
this.CenterX=0;
this.CenterY=0;
this.CenterZ=0;
this.Frames=0;
this.TrjPath="";
this.BoxX=0;
this.BoxY=0;
this.BoxZ=0;
this.GetChain=function()
{
return this.LstChain;
}
this.GetBonds=function()
{
return this.LstBonds;
}
this.GetAtoms=function()
{
return this.LstAtoms;
}
this.GetBSkeleton=function()
{
return this.LstBondsSkeleton;
}
this.GetBoxX=function()
{
return this.BoxX;
}
this.GetBoxY=function()
{
return this.BoxY;
}
this.GetBoxZ=function()
{
return this.BoxZ;
}
}
function Atom(number,x,y,z,state,element,nameatom)
{
this.X=x;
this.Y=y;
this.Z=z;
this.State=state;
this.NumberAtom=number;
this.Element=element;
this.NameAtom=nameatom;
this.Aminoacid=null;
this.AminoNum=null;
this.ColorName=null;
this.ColorRGB=null;
this.ColorRGBDiffuse=null;
this.Seleccionado=false; //
this.Representation=null;
this.LstLinea=[];
this.LstLineaSke=[];
this.GetLstidLinea=function()
{
return this.LstidLinea;
}
//Esta parte es para los bloques
this.BloqueWire=0;
this.PositionBWire=0;
this.BloqueSolid=0;
this.PositionBSolid=0;
////////////////////////
//para mantener o no un color diferente
this.ColorDiferente = false;
this.ColorDos=null;
this.id=null; //es para poner el órden en el que aparecen
this.idChain=null;
}
function createBonds(main)
{
//console.log ("HTMoL3: will try to create bonds");
var bond= new Bond();
for (var t in molecule.GetChain())
{
var chn=molecule.GetChain()[t];
//console.log ("for chain "+chn.Name);
for(var r in chn.GetAminoacid())
{
var amn=chn.GetAminoacid()[r];
//if(amn.Name=="GLU") console.log ("for aminoacid "+amn.Name+" "+amn.Number);
for(var s in amn.GetAtoms())
{
var atom=amn.GetAtoms()[s];
//if(amn.Name=="GLU") console.log ("for atom '"+atom.NameAtom+"' "+atom.Element);
for(var b in AtomsBonds[atom.NameAtom])
{
var val=AtomsBonds[atom.NameAtom][b];
//if(amn.Name=="GLU") console.log ("for bond "+val);
for(var i in amn.GetAtoms())
{
var atomb=amn.GetAtoms()[i];
if(val==atomb.NameAtom)
{
bond=main.ObjP.AddBond(bond,atom,atomb);
//if(amn.Name=="GLU") console.log("HTMoL3: added bond between "+atom.NameAtom+" and "+atomb.NameAtom);
}
}
}
}
}
}
}
function Process()
{
this.Model= new Molecule();
this.ReadFile= function(URL)
{
var text = $.ajax({
url: URL,
dataType: 'text',
// "false" value gives browser warning "[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience."
// "true" value breaks the app, no time to debug
async: false
}).responseText;
if (text!=null&&text.substr(0,6)!="<html>"){
return this.Parse(text);
}
else
return null;
}
this.Parse= function(text)
{
var cont=0;
this.Model=new Molecule();
var cmpAmino='',cmpChain='';
var chain=new Chain();
var aminoacid=new Aminoacid();
var bond=new Bond();
var bondS= new BondSkeleton();
var lines=text.split("\n");
var val,val2;
var AtomCount=0;
var contSkele=0;
var id=0;
var ChainCont=1;
contBonds=0;
contBS=0;
CzPers=10;
var RGB_Diffuse = [,,]; //para asignarle un único valor de color difuso a cada átomo para distinguirlo de los demás en la selección
//la que no se toma sería [0][0][0] entonces comenzaría con [1][0][0] y terminaría en [255][255][254]
var R=0;
var G=0;
var B=0;
var Scala=0.003921568627451;
for(var i=0; i<lines.length; ++i)
{
if(lines[i].substr(0,7)=="NFRAMES")
{
this.Model.Frames=lines[i].substr(10);
console.log("HTMoL3: Expecting "+this.Model.Frames+" frames");
}
if(lines[i].substr(0,7)=="TRJPATH")
{
this.Model.TrjPath=lines[i].substr(10);
console.log("from trajectory file "+this.Model.TrjPath+"");
}
if(lines[i].substr(0,6)=="HEADER")
{
this.Model.Name=lines[i].substr(62,4);
}
if(lines[i].substr(0,6)=="CRYST1")
{
this.Model.BoxX=parseFloat(lines[i].substr(7,8));
this.Model.BoxY=parseFloat(lines[i].substr(16,8));
this.Model.BoxZ=parseFloat(lines[i].substr(25,8));
//console.log("Box X: "+this.Model.BoxX+" Box Y: "+this.Model.BoxY+" Box Z: "+this.Model.BoxZ);
}
// According to http://www.wwpdb.org/documentation/file-format-content/format33/sect9.html#ATOM
// COLUMNS DATA TYPE FIELD DEFINITION
// -------------------------------------------------------------------------------------
// 1 - 6 Record name "ATOM "
// 7 - 11 Integer serial Atom serial number.
// 13 - 16 Atom name Atom name.
// 17 Character altLoc Alternate location indicator.
// 18 - 20 Residue name resName Residue name.
// 22 Character chainID Chain identifier.
// 23 - 26 Integer resSeq Residue sequence number.
// 27 AChar iCode Code for insertion of residues.
// 31 - 38 Real(8.3) x Orthogonal coordinates for X in Angstroms.
// 39 - 46 Real(8.3) y Orthogonal coordinates for Y in Angstroms.
// 47 - 54 Real(8.3) z Orthogonal coordinates for Z in Angstroms.
// 55 - 60 Real(6.2) occupancy Occupancy.
// 61 - 66 Real(6.2) tempFactor Temperature factor.
// 77 - 78 LString(2) element Element symbol, right-justified.
// 79 - 80 LString(2) charge Charge on the atom.
// Alignment of one-letter atom name such as C starts at column 14, while two-letter atom name such as FE starts at column 13.
// Atom nomenclature begins with atom type
// Non-blank alphanumerical character is used for chain identifier
// Beware lines[] index start at 0, not 1
if(lines[i].substr(0,4)=="ATOM")
{
var PDBRecordName = lines[i].substr(0,6);
var PDBserial = parseInt(lines[i].substr(6,5),10); // so you get a decimal number even with a leading 0 and an old browser ([IE8, Firefox 20, Chrome 22 and older][1])
var PDBname = lines[i].substr(12,4); PDBname = PDBname.trim(); // removes whitespace from both sides
if(/^\d/.test(PDBname)) // if found, removes a number found at the begining of atom name
{
//console.log("HTMoL: Parsing PDB file (Process). Found a number in atom name: "+PDBname);
PDBname = PDBname.substring(1);
//console.log("changed it to: "+PDBname);
}
var PDBaltLoc = lines[i].substr(16,1);
var PDBresName = lines[i].substr(17,3);
var PDBchainID = lines[i].substr(21,1);
var PDBresSeq = parseInt(lines[i].substr(22,4),10); // same as above
var PDBiCode = lines[i].substr(26,1);
var PDBx = parseFloat(lines[i].substr(30,8));
var PDBy = parseFloat(lines[i].substr(38,8));
var PDBz = parseFloat(lines[i].substr(46,8));
var PDBoccupancy = lines[i].substr(54,6);
var PDBtempFactor = lines[i].substr(60,6);
// var PDBelement = lines[i].substr(76,2);
var PDBelement = PDBname.trim().substr(0,1); // removes whitespace from both sides of name and use first character
var PDBcharge = lines[i].substr(78,2);
//console.log("serial:"+PDBserial+" name:"+PDBname+" resName:"+PDBresName+" chainID:"+PDBchainID+" resSeq:"+PDBresSeq+" element:"+PDBelement);
var atom=new Atom
(
PDBserial,
PDBx,
PDBy,
PDBz,
'Active', //state
PDBelement,
PDBname
//lines[i].substr(11,6).trim().replace(/\s/g,"&") //nombre
);
if(cont==0)
{
cmpAmino=PDBresSeq; //lines[i].substr(22,4); //Número del aminoácido en el que aparece
cmpChain=PDBchainID; //lines[i].substr(20,2);
aminoacid=new Aminoacid(cmpAmino,PDBresName,'Active'); //alguno de los 20
chain=new Chain(cmpChain,'Active');
}
if(cmpAmino!=PDBresSeq) // Cambio el residuo. Número del aminoácido en el que aparece
{
cmpAmino=PDBresSeq; //lines[i].substr(22,4);
chain.LstAminoAcid.push(aminoacid);
aminoacid=new Aminoacid(cmpAmino,PDBresName,'Active');
}
if(cmpChain!=PDBchainID) // Cambio la cadena
{
cmpChain=PDBchainID; //lines[i].substr(20,2);
this.Model.LstChain.push(chain);
chain=new Chain(cmpChain,'Active');
ChainCont=ChainCont + 1;
}
// Checking correct assignments
// Atom(number,x,y,z,state,element,nameatom)
// this.X=x;
// this.Y=y;
// this.Z=z;
// this.State=state;
// this.NumberAtom=number;
// this.Element=element;
// this.NameAtom=nameatom;
// Aminoacid(number,name,state)
// this.Number=number;
// this.Name=name;
// this.State=state;
// Chain(name,state)
// this.Name=name;
//console.log("NumberAtom:"+atom.NumberAtom+" NameAtom:"+atom.NameAtom+" resName:"+aminoacid.Name+" chainID:"+chain.Name+" resSeq:"+aminoacid.Number+" element:"+atom.Element);
aminoacid.LstAtoms.push(atom);
this.Model.LstAtoms.push(atom);
atom.Aminoacid=aminoacid.Name;
atom.AminoNum=aminoacid.Number;
if(atom.NameAtom=='C'|| atom.NameAtom=='O3\'')
{
var atomtmp=atom;
}
if((atom.NameAtom=='N'|| atom.NameAtom=='P') && cont>1)
{
bond=this.AddBond(bond,atomtmp,atom);
}
/////////////////////////// This part is for Skeletom´s Atoms ////////////////////////////////////////////
if(atom.NameAtom=='CA'|| atom.NameAtom=='P')
{
if (contSkele==0) {
var atomtmp2=atom;
}
aminoacid.Type='T';
//atom.Aminoacid=aminoacid;
chain.LstSkeleton.push(atom);
if (contSkele>0) {
bondS = this.AddBondSkeleton(bondS,atomtmp2,atom);
atomtmp2.LstLineaSke.push(bondS);
atom.LstLineaSke.push(bondS);
atomtmp2=atom;
}
contSkele++;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////
this.Model.CenterX+=atom.X;
this.Model.CenterY+=atom.Y;
this.Model.CenterZ+=atom.Z;
cont++;
/////////////////////////
// código para centrar bien la cámara
var atmX = Math.abs(atom.X);
var atmY = Math.abs(atom.Y);
if (atmX < atmY)
{
if (CzPers < atmY)
{
CzPers = atmY;
}
}
else
{
if (CzPers < atmX)
{
CzPers = atmX;
}
}
////////////////////////
id++;
atom.id=id;
atom.idChain=ChainCont;
//Asignación del color difuso a cáda átomo
R=R+1;
if (R==255)
{
R=0;
G=G+1;
if (G==255)
{
G=0;
B=B+1;
}
}
atom.ColorRGBDiffuse=[R*Scala,G*Scala,B*Scala];
//en esta parte se asigna el color al átom
AsignaColor(atom);
}
}
this.Model.CenterX=this.Model.CenterX/this.Model.LstAtoms.length;
this.Model.CenterY=this.Model.CenterY/this.Model.LstAtoms.length;
this.Model.CenterZ=this.Model.CenterZ/this.Model.LstAtoms.length
chain.LstAminoAcid.push(aminoacid);
this.Model.LstChain.push(chain);
return this.Model;
}
this.AddBond=function(bond,atom,union)
{
try
{
var distancia=Math.sqrt(Math.pow(atom.X-union.X,2)+Math.pow(atom.Y-union.Y,2)+Math.pow(atom.Z-union.Z,2));
if(distancia<3) //2
{
bond.LstAtoms.push(atom);
bond.LstAtoms.push(union);
bond.id=contBonds;
bond.State='Active';
atom.LstLinea.push(bond);
union.LstLinea.push(bond);
this.Model.LstBonds.push(bond);
contBonds++;
}
}catch(e)
{console.log("HTMoL3: Error adding bond ("+e+") between atom "+atom.NameAtom+" and "+union.NameAtom);}
return bond=new Bond();
}
this.AddBondSkeleton=function(bond,atom,union)
{
try
{
var distancia=Math.sqrt(Math.pow(atom.X-union.X,2)+Math.pow(atom.Y-union.Y,2)+Math.pow(atom.Z-union.Z,2));
if(distancia<8)
{
bond.LstAtoms.push(atom);
bond.LstAtoms.push(union);
bond.id=contBS;
this.Model.LstBondsSkeleton.push(bond);
contBS++;
}
}catch(e)
{}
return bond=new BondSkeleton();
}
}