From 5cf1b98bd20f3a05bb797784755f1df24bc8cd61 Mon Sep 17 00:00:00 2001
From: "Wang, Jiyao"
Date: Tue, 5 Nov 2019 11:44:09 -0500
Subject: [PATCH] Display/output salt bridges; color helices and sheets with
spectrum in the menu "Color > Secondary > Spectrum".
---
CHANGELOG.md | 2 +
README.md | 2 +-
icn3d.html | 13 +-
package.json | 2 +-
src/icn3d/display/display_common.js | 68 ++++-
src/icn3d/display/display_full.js | 62 +++-
src/icn3d/icn3d.js | 2 +
src/icn3d/loadpdb.js | 2 -
src/icn3d/other.js | 30 ++
src/icn3d/other_full.js | 64 ++++-
src/icn3dui/common_full_simple.js | 6 +-
src/icn3dui/full_ui.js | 351 ++++++++++++++++-------
src/icn3dui/html/set_html.js | 49 +++-
src/icn3dui/parsers/mmcif_mmdb_parser.js | 14 +-
src/icn3dui/selection/commands.js | 64 ++++-
15 files changed, 574 insertions(+), 157 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 27286541..693d1d72 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,6 @@
## Change Log
+[icn3d-2.8.3](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-2.8.3.zip) was release on November 5, 2019. Display/output salt bridges; color helices and sheets with spectrum in the menu "Color > Secondary > Spectrum".
+
[icn3d-2.8.2](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-2.8.2.zip) was release on October 29, 2019. Reduced the size of three.js (version 103) library. Added links to dbSNP in the mouseover texts of SNP annotations.
[icn3d-2.8.1](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-2.8.1.zip) was release on October 21, 2019. Fixed the 2D interaction display in structure alignment. The bug was introduced in the last release.
diff --git a/README.md b/README.md
index bc460f07..f61fdea9 100644
--- a/README.md
+++ b/README.md
@@ -24,7 +24,7 @@ We provided two types of iCn3D widgets: [basic interface](https://www.ncbi.nlm.n
Either of these widgets could be easily added to your own web pages as shown in the section of "Embed iCn3D with iframe or JavaScript libraries" below.
-Complete package of iCn3D including Three.js and jQuery can be downloaded from [https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-2.8.2.zip](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-2.8.2.zip). The "Download ZIP" link in this page does not include third-party libraries.
+Complete package of iCn3D including Three.js and jQuery can be downloaded from [https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-2.8.3.zip](https://www.ncbi.nlm.nih.gov/Structure/icn3d/icn3d-2.8.3.zip). The "Download ZIP" link in this page does not include third-party libraries.
## Usage
diff --git a/icn3d.html b/icn3d.html
index 98fcdff8..f0f1ee1d 100644
--- a/icn3d.html
+++ b/icn3d.html
@@ -601,7 +601,7 @@
How to embed iCn3D Structure Viewer in your html page:Embed using iframe
To embed iCn3D Structure Viewer in your own HTML page using iframe, simply add the following to your page:
-
+icn3d-2.8.3 was release on November 5, 2019. Display/output salt bridges; color helices and sheets with spectrum in the menu "Color > Secondary > Spectrum".
+
icn3d-2.8.2 was release on October 29, 2019. Reduced the size of three.js (version 103) library. Added links to dbSNP in the mouseover texts of SNP annotations.
diff --git a/package.json b/package.json
index 66360e01..f598aeca 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "icn3d",
- "version": "2.8.2",
+ "version": "2.8.3",
"description": "iCn3D Structure Viewer",
"main": "index.html",
"scripts": {
diff --git a/src/icn3d/display/display_common.js b/src/icn3d/display/display_common.js
index 42cbddfe..68cebd08 100644
--- a/src/icn3d/display/display_common.js
+++ b/src/icn3d/display/display_common.js
@@ -90,11 +90,11 @@ iCn3D.prototype.setColorByOptions = function (options, atoms, bUseInputColor) {
if(!atom.het) ++cnt;
}
- var lastTerSerialInv = 1 / cnt;
+ var lastTerSerialInv = (cnt > 1) ? 1 / (cnt - 1) : 1;
for (var i in atoms) {
var atom = this.atoms[i];
- atom.color = atom.het ? this.atomColors[atom.elem] || this.defaultAtomColor : new THREE.Color().setHSL(2 / 3 * (1 - idx++ * lastTerSerialInv), 1, 0.45);
- //atom.color = this.atomColors[atom.elem] || this.defaultAtomColor;
+ //atom.color = atom.het ? this.atomColors[atom.elem] || this.defaultAtomColor : new THREE.Color().setHSL(2 / 3 * (1 - idx++ * lastTerSerialInv), 1, 0.45);
+ atom.color = atom.het ? this.atomColors[atom.elem] || this.defaultAtomColor : new THREE.Color().setHSL(3 / 4 * (1 - idx++ * lastTerSerialInv), 1, 0.45);
this.atomPrevColors[i] = atom.color;
}
@@ -149,6 +149,68 @@ iCn3D.prototype.setColorByOptions = function (options, atoms, bUseInputColor) {
break;
+ case 'secondary structure spectrum':
+ var idx = 0, cnt = 0;
+
+ var ssArray = [], coilArray = [];
+ var prevI = -9999, start;
+ var currSS, prevSS, currResi, prevResi;
+ for (var i in atoms) {
+ // only for proteins
+ if(!this.proteins.hasOwnProperty(i)) continue;
+
+ var atom = this.atoms[i];
+
+ currSS = atom.ss;
+ currResi = atom.resi;
+
+ if(prevI == -9999) start = parseInt(i);
+
+ if(prevI != -9999 && (currSS != prevSS || Math.abs(currResi - prevResi) > 1) ) {
+ if(prevSS == 'coil') {
+ coilArray.push([start, prevI]);
+ }
+ else {
+ ssArray.push([start, prevI]);
+ }
+ start = i;
+ }
+
+ prevI = parseInt(i);
+ prevSS = currSS;
+ prevResi = currResi;
+ }
+
+ if(prevSS == 'coil') {
+ coilArray.push([start, prevI]);
+ }
+ else {
+ ssArray.push([start, prevI]);
+ }
+
+ cnt = ssArray.length;
+ var lastTerSerialInv = (cnt > 1) ? 1 / (cnt - 1) : 1;
+ for (var i = 0, il = ssArray.length; i < il; ++i) {
+ //var color = new THREE.Color().setHSL(2 / 3 * (1 - idx++ * lastTerSerialInv), 1, 0.45);
+ var color = new THREE.Color().setHSL(3 / 4 * (1 - idx++ * lastTerSerialInv), 1, 0.45);
+
+ for(var serial = ssArray[i][0]; serial <= ssArray[i][1]; ++serial) {
+ var atom = this.atoms[serial];
+ atom.color = color;
+ this.atomPrevColors[serial] = atom.color;
+ }
+ }
+
+ var color = this.ssColors2['coil']
+ for (var i = 0, il = coilArray.length; i < il; ++i) {
+ for(var serial = coilArray[i][0]; serial <= coilArray[i][1]; ++serial) {
+ var atom = this.atoms[serial];
+ atom.color = color;
+ this.atomPrevColors[serial] = atom.color;
+ }
+ }
+ break;
+
case 'residue':
for (var i in atoms) {
var atom = this.atoms[i];
diff --git a/src/icn3d/display/display_full.js b/src/icn3d/display/display_full.js
index 0eaaa613..5c4b8ad9 100644
--- a/src/icn3d/display/display_full.js
+++ b/src/icn3d/display/display_full.js
@@ -69,6 +69,29 @@ iCn3D.prototype.hideHbonds = function () {
}
};
+iCn3D.prototype.hideSaltbridge = function () {
+ this.opts["saltbridge"] = "no";
+ if(this.lines === undefined) this.lines = {};
+ this.lines['saltbridge'] = [];
+ this.saltbridgepnts = [];
+
+ for(var i in this.atoms) {
+ this.atoms[i].style2 = 'nothing';
+ }
+
+ for(var i in this.sidec) {
+ if(this.hAtoms.hasOwnProperty(i)) {
+ this.atoms[i].style2 = this.opts["sidec"];
+ }
+ }
+
+ for(var i in this.water) {
+ if(this.hAtoms.hasOwnProperty(i)) {
+ this.atoms[i].style = this.opts["water"];
+ }
+ }
+};
+
iCn3D.prototype.applySsbondsOptions = function (options) {
if(options === undefined) options = this.opts;
@@ -477,16 +500,46 @@ iCn3D.prototype.applySurfaceOptions = function (options) {
}
};
+iCn3D.prototype.setHbondsSaltbridge = function (options, bSaltbridge) {
+ var hbond_saltbridge = (bSaltbridge !== undefined && bSaltbridge) ? 'saltbridge' : 'hbond';
+ var hbonds_saltbridge = (bSaltbridge !== undefined && bSaltbridge) ? 'saltbridge' : 'hbonds';
+
+ this.lines[hbond_saltbridge] = [];
+
+ if (options[hbonds_saltbridge].toLowerCase() === 'yes') {
+ var color = '#00FF00';
+ var pnts = (bSaltbridge !== undefined && bSaltbridge) ? this.saltbridgepnts : this.hbondpnts;
+
+ for (var i = 0, lim = Math.floor(pnts.length / 2); i < lim; i++) {
+ var line = {};
+ line.position1 = pnts[2 * i].coord;
+ line.serial1 = pnts[2 * i].serial;
+ line.position2 = pnts[2 * i + 1].coord;
+ line.serial2 = pnts[2 * i + 1].serial;
+ line.color = color;
+ line.dashed = true;
+
+ // only draw bonds connected with currently displayed atoms
+ if(line.serial1 !== undefined && line.serial2 !== undefined && !this.dAtoms.hasOwnProperty(line.serial1) && !this.dAtoms.hasOwnProperty(line.serial2)) continue;
+
+ //if(this.lines[hbond_saltbridge] === undefined) this.lines[hbond_saltbridge] = [];
+ this.lines[hbond_saltbridge].push(line);
+ }
+ }
+};
+
iCn3D.prototype.applyOtherOptions = function (options) {
if(options === undefined) options = this.opts;
if(this.lines !== undefined) {
- this.lines['hbond'] = [];
+ //this.lines['hbond'] = [];
+ //this.lines['saltbridge'] = [];
//common part options
- // lines
- //if (options.hbonds.toLowerCase() === 'yes' || options.ncbonds.toLowerCase() === 'yes') {
+ // hbond lines
+ this.setHbondsSaltbridge(options);
+/*
if (options.hbonds.toLowerCase() === 'yes') {
var color = '#00FF00';
var pnts = this.hbondpnts;
@@ -509,6 +562,9 @@ iCn3D.prototype.applyOtherOptions = function (options) {
//this.createLines(this.lines);
}
+*/
+ // salt bridge lines
+ this.setHbondsSaltbridge(options, true);
if (this.pairArray !== undefined && this.pairArray.length > 0) {
this.updateStabilizer(); // to update this.stabilizerpnts
diff --git a/src/icn3d/icn3d.js b/src/icn3d/icn3d.js
index 47cacc6f..cfae3daa 100644
--- a/src/icn3d/icn3d.js
+++ b/src/icn3d/icn3d.js
@@ -197,6 +197,7 @@ var iCn3D = function (id) {
//labels: 'no',
//effect: 'none',
hbonds: 'no',
+ saltbridge: 'no',
//stabilizer: 'no',
ssbonds: 'no',
//ncbonds: 'no',
@@ -1169,6 +1170,7 @@ iCn3D.prototype = {
this.calphas = {};
this.hbondpnts = [];
+ this.saltbridgepnts = [];
this.stabilizerpnts = [];
//this.ncbondpnts = []; // non-covalent bonds
diff --git a/src/icn3d/loadpdb.js b/src/icn3d/loadpdb.js
index 5d371dba..00ad02d8 100644
--- a/src/icn3d/loadpdb.js
+++ b/src/icn3d/loadpdb.js
@@ -132,8 +132,6 @@ iCn3D.prototype.loadPDB = function (src) {
this.ssbondpnts[id].push(resid1);
this.ssbondpnts[id].push(resid2);
-
-console.log("this.ssbondpnts: " + JSON.stringify(this.ssbondpnts));
} else if (record === 'REMARK') {
var type = parseInt(line.substr(7, 3));
// from GLMol
diff --git a/src/icn3d/other.js b/src/icn3d/other.js
index 01c9a66f..33787f70 100644
--- a/src/icn3d/other.js
+++ b/src/icn3d/other.js
@@ -738,6 +738,36 @@ iCn3D.prototype.addResiudeLabels = function (atoms, bSchematic, alpha) {
this.removeHlObjects();
};
+iCn3D.prototype.addAtomLabels = function (atoms) {
+ var size = 18;
+ var background = "#CCCCCC";
+
+ var atomsHash = this.intHash(this.hAtoms, atoms);
+
+ if(this.labels['residue'] === undefined) this.labels['residue'] = [];
+
+ for(var i in atomsHash) {
+ var atom = this.atoms[i];
+
+ var label = {}; // Each label contains 'position', 'text', 'color', 'background'
+
+ label.position = atom.coord;
+
+ label.bSchematic = 0;
+
+ label.text = atom.name;
+ label.size = size;
+
+ var atomColorStr = atom.color.getHexString().toUpperCase();
+ label.color = (atomColorStr === "CCCCCC" || atomColorStr === "C8C8C8") ? "#888888" : "#" + atomColorStr;
+ label.background = background;
+
+ this.labels['residue'].push(label);
+ }
+
+ this.removeHlObjects();
+};
+
iCn3D.prototype.setCenter = function(center) {
if(!this.bChainAlign) {
this.mdl.position.set(0,0,0);
diff --git a/src/icn3d/other_full.js b/src/icn3d/other_full.js
index 5fa8d934..b61cbab0 100644
--- a/src/icn3d/other_full.js
+++ b/src/icn3d/other_full.js
@@ -3,7 +3,7 @@
*/
// get hbonds between "molecule" and "chemical"
-iCn3D.prototype.calculateChemicalHbonds = function (startAtoms, targetAtoms, threshold) { var me = this;
+iCn3D.prototype.calculateChemicalHbonds = function (startAtoms, targetAtoms, threshold, bSaltbridge) { var me = this;
if(Object.keys(startAtoms).length === 0 || Object.keys(targetAtoms).length === 0) return;
me.resid2Residhash = {};
@@ -16,8 +16,14 @@ iCn3D.prototype.calculateChemicalHbonds = function (startAtoms, targetAtoms, thr
for (var i in startAtoms) {
var atom = startAtoms[i];
- if(atom.elem === "N" || atom.elem === "O" || atom.elem === "F") { // calculate hydrogen bond
- chain_resi_atom = atom.structure + "_" + atom.chain + "_" + atom.resi + "_" + atom.name;
+ // salt bridge: calculate hydrogen bond between Lys/Arg and Glu/Asp
+ // hbonds: calculate hydrogen bond
+ var bAtomCond = (bSaltbridge !== undefined && bSaltbridge) ? ( (atom.resn === 'ARG' || atom.resn === 'LYS') && atom.elem === "N" && atom.name !== "N")
+ || ( (atom.resn === 'GLU' || atom.resn === 'ASP') && atom.elem === "O" && atom.name !== "O") : atom.elem === "N" || atom.elem === "O" || atom.elem === "F";
+
+ if(bAtomCond) {
+ chain_resi = atom.structure + "_" + atom.chain + "_" + atom.resi;
+ chain_resi_atom = chain_resi + "_" + atom.name;
atomHbond[chain_resi_atom] = atom;
}
@@ -29,17 +35,31 @@ iCn3D.prototype.calculateChemicalHbonds = function (startAtoms, targetAtoms, thr
for (var i in targetAtoms) {
var atom = targetAtoms[i];
+ // salt bridge: calculate hydrogen bond between Lys/Arg and Glu/Asp
+ // hbonds: calculate hydrogen bond
+ var bAtomCond = (bSaltbridge !== undefined && bSaltbridge) ? ( (atom.resn === 'ARG' || atom.resn === 'LYS') && atom.elem === "N" && atom.name !== "N")
+ || ( (atom.resn === 'GLU' || atom.resn === 'ASP') && atom.elem === "O" && atom.name !== "O") : atom.elem === "N" || atom.elem === "O" || atom.elem === "F";
+
var currResiHash = {};
- if(atom.elem === "N" || atom.elem === "O" || atom.elem === "F") { // calculate hydrogen bond
+ if(bAtomCond) {
chain_resi = atom.structure + "_" + atom.chain + "_" + atom.resi;
chain_resi_atom = chain_resi + "_" + atom.name;
- var oriResidName = chain_resi + ' ' + atom.resn;
+ //var oriResidName = atom.resn + ' ' + chain_resi_atom;
+ var oriResidName = atom.resn + ' $' + atom.structure + '.' + atom.chain + ':' + atom.resi + '@' + atom.name;
if(me.resid2Residhash[oriResidName] === undefined) me.resid2Residhash[oriResidName] = {};
for (var j in atomHbond) {
+ if(bSaltbridge !== undefined && bSaltbridge) {
+ // skip both positive orboth negative cases
+ if( ( (atom.resn === 'LYS' || atom.resn === 'ARG') && (atomHbond[j].resn === 'LYS' || atomHbond[j].resn === 'ARG') ) ||
+ ( (atom.resn === 'GLU' || atom.resn === 'ASP') && (atomHbond[j].resn === 'GLU' || atomHbond[j].resn === 'ASP') ) ) {
+ continue;
+ }
+ }
+
// skip same protein residue
- if(chain_resi == j.substr(0, j.lastIndexOf('_')) && this.proteins.hasOwnProperty(atomHbond[j].serial)) continue;
+ if(chain_resi == j.substr(0, j.lastIndexOf('_') ) && this.proteins.hasOwnProperty(atomHbond[j].serial)) continue;
var xdiff = Math.abs(atom.coord.x - atomHbond[j].coord.x);
if(xdiff > threshold) continue;
@@ -54,16 +74,26 @@ iCn3D.prototype.calculateChemicalHbonds = function (startAtoms, targetAtoms, thr
if(dist > maxlengthSq) continue;
// output hydrogen bonds
- this.hbondpnts.push({'serial': atom.serial, 'coord': atom.coord});
- this.hbondpnts.push({'serial': atomHbond[j].serial, 'coord': atomHbond[j].coord});
+ if(bSaltbridge !== undefined && bSaltbridge) {
+ this.saltbridgepnts.push({'serial': atom.serial, 'coord': atom.coord});
+ this.saltbridgepnts.push({'serial': atomHbond[j].serial, 'coord': atomHbond[j].coord});
+ }
+ else {
+ this.hbondpnts.push({'serial': atom.serial, 'coord': atom.coord});
+ this.hbondpnts.push({'serial': atomHbond[j].serial, 'coord': atomHbond[j].coord});
+ }
hbondsAtoms = this.unionHash(hbondsAtoms, this.residues[atom.structure + "_" + atom.chain + "_" + atom.resi]);
hbondsAtoms = this.unionHash(hbondsAtoms, this.residues[atomHbond[j].structure + "_" + atomHbond[j].chain + "_" + atomHbond[j].resi]);
residueHash[chain_resi] = 1;
- var residName = atomHbond[j].structure + "_" + atomHbond[j].chain + "_" + atomHbond[j].resi + " " + atomHbond[j].resn;
- me.resid2Residhash[oriResidName][residName] = 1;
+ //var residName = atomHbond[j].resn + " " + atomHbond[j].structure + "_" + atomHbond[j].chain + "_" + atomHbond[j].resi + '_' + atomHbond[j].name;
+ var residName = atomHbond[j].resn + ' $' + atomHbond[j].structure + '.' + atomHbond[j].chain + ':' + atomHbond[j].resi + '@' + atomHbond[j].name;
+
+ if(me.resid2Residhash[oriResidName][residName] === undefined || me.resid2Residhash[oriResidName][residName] > dist) {
+ me.resid2Residhash[oriResidName][residName] = dist.toFixed(1);
+ }
} // end of for (var j in atomHbond) {
}
} // end of for (var i in targetAtoms) {
@@ -75,7 +105,6 @@ iCn3D.prototype.calculateChemicalHbonds = function (startAtoms, targetAtoms, thr
for(var j in this.residues[residueArray[i]]) {
// all atoms should be shown for hbonds
this.atoms[j].style2 = 'stick';
- //this.atoms[j].style2 = 'lines';
}
}
@@ -148,7 +177,9 @@ iCn3D.prototype.getChainsFromAtoms = function(atomsHash) {
var oriResidName;
if(bGetPairs) {
- oriResidName = oriAtom.structure + '_' + oriAtom.chain + '_' + oriAtom.resi + ' ' + oriAtom.resn;
+ //oriResidName = oriAtom.structure + '_' + oriAtom.chain + '_' + oriAtom.resi + '_' + oriAtom.name + ' ' + oriAtom.resn;
+ //oriResidName = oriAtom.structure + '_' + oriAtom.chain + '_' + oriAtom.resi + ' ' + oriAtom.resn;
+ oriResidName = '$' + oriAtom.structure + '.' + oriAtom.chain + ':' + oriAtom.resi + ' ' + oriAtom.resn;
if(me.resid2Residhash[oriResidName] === undefined) me.resid2Residhash[oriResidName] = {};
}
@@ -167,8 +198,13 @@ iCn3D.prototype.getChainsFromAtoms = function(atomsHash) {
var residName;
if(bGetPairs) {
- residName = atom.structure + '_' + atom.chain + '_' + atom.resi + ' ' + atom.resn;
- me.resid2Residhash[oriResidName][residName] = 1
+ //residName = atom.structure + '_' + atom.chain + '_' + atom.resi + '_' + atom.name + ' ' + atom.resn;
+ //residName = atom.structure + '_' + atom.chain + '_' + atom.resi + ' ' + atom.resn;
+ residName = '$' + atom.structure + '.' + atom.chain + ':' + atom.resi + ' ' + atom.resn;
+ var dist = Math.sqrt(atomDistSq).toFixed(1);
+ if(me.resid2Residhash[oriResidName][residName] === undefined || me.resid2Residhash[oriResidName][residName] > dist) {
+ me.resid2Residhash[oriResidName][residName] = dist;
+ }
}
}
}
diff --git a/src/icn3dui/common_full_simple.js b/src/icn3dui/common_full_simple.js
index 552d7f3b..4fb5e8e0 100644
--- a/src/icn3dui/common_full_simple.js
+++ b/src/icn3dui/common_full_simple.js
@@ -94,6 +94,8 @@ iCn3DUI.prototype.showTitle = function() { var me = this;
if(me.icn3d.molTitle !== undefined && me.icn3d.molTitle !== '') {
var title = me.icn3d.molTitle;
+ var titlelinkColor = (me.opts['background'] == 'white' || me.opts['background'] == 'grey') ? 'black' : me.GREYD;
+
if(me.inputid === undefined) {
if(me.icn3d.molTitle.length > 40) title = me.icn3d.molTitle.substr(0, 40) + "...";
@@ -102,7 +104,7 @@ iCn3DUI.prototype.showTitle = function() { var me = this;
else if(me.cfg.cid !== undefined) {
var url = me.getLinkToStructureSummary();
- $("#" + me.pre + "title").html("PubChem CID " + me.inputid.toUpperCase() + ": " + title);
+ $("#" + me.pre + "title").html("PubChem CID " + me.inputid.toUpperCase() + ": " + title);
}
else if(me.cfg.align !== undefined) {
$("#" + me.pre + "title").html(title);
@@ -121,7 +123,7 @@ iCn3DUI.prototype.showTitle = function() { var me = this;
//var asymmetricStr = (me.bAssemblyUseAsu) ? " (Asymmetric Unit)" : "";
var asymmetricStr = "";
- $("#" + me.pre + "title").html("PDB ID " + me.inputid.toUpperCase() + "" + asymmetricStr + ": " + title);
+ $("#" + me.pre + "title").html("PDB ID " + me.inputid.toUpperCase() + "" + asymmetricStr + ": " + title);
}
}
else {
diff --git a/src/icn3dui/full_ui.js b/src/icn3dui/full_ui.js
index 43643fd3..fd0d4932 100644
--- a/src/icn3dui/full_ui.js
+++ b/src/icn3dui/full_ui.js
@@ -15,7 +15,7 @@ if (!$.ui.dialog.prototype._makeDraggableBase) {
var iCn3DUI = function(cfg) {
var me = this;
- this.REVISION = '2.8.2';
+ this.REVISION = '2.8.3';
me.bFullUi = true;
@@ -157,6 +157,7 @@ var iCn3DUI = function(cfg) {
me.opts['water'] = 'nothing'; //sphere, dot, nothing
me.opts['ions'] = 'sphere'; //sphere, dot, nothing
me.opts['hbonds'] = 'no'; //yes, no
+ me.opts['saltbridge'] = 'no'; //yes, no
//me.opts['stabilizer'] = 'no'; //yes, no
me.opts['ssbonds'] = 'yes'; //yes, no
me.opts['rotationcenter'] = 'molecule center'; //molecule center, pick center, display center
@@ -668,7 +669,8 @@ iCn3DUI.prototype = {
me.loadScript(me.cfg.command);
}
else {
- alert("Please use the \"File\" menu to retrieve a structure of interest or to display a local file.");
+ //alert("Please use the \"File\" menu to retrieve a structure of interest or to display a local file.");
+ me.openDialog(me.pre + 'dl_mmdbid', 'Please input MMDB or PDB ID');
}
});
@@ -1120,27 +1122,17 @@ iCn3DUI.prototype = {
else {
if(me.icn3d.defNames2Residues[commandname] !== undefined && me.icn3d.defNames2Residues[commandname].length > 0) {
for(var j = 0, jl = me.icn3d.defNames2Residues[commandname].length; j < jl; ++j) {
- var serial = me.icn3d.defNames2Residues[commandname][j];
+ var resid = me.icn3d.defNames2Residues[commandname][j];
- if(serial !== undefined) {
- var atom = me.icn3d.atoms[serial];
- var resid = atom.structure + '_' + atom.chain + '_' + atom.resi;
-
- residuesHash = me.icn3d.unionHash(residuesHash, me.icn3d.residues[resid]);
- }
+ residuesHash = me.icn3d.unionHash(residuesHash, me.icn3d.residues[resid]);
}
}
if(me.icn3d.defNames2Atoms[commandname] !== undefined && me.icn3d.defNames2Atoms[commandname].length > 0) {
for(var j = 0, jl = me.icn3d.defNames2Atoms[commandname].length; j < jl; ++j) {
- var serial = me.icn3d.defNames2Atoms[commandname][j];
+ var resid = me.icn3d.defNames2Atoms[commandname][j];
- if(serial !== undefined) {
- var atom = me.icn3d.atoms[serial];
- var resid = atom.structure + '_' + atom.chain + '_' + atom.resi;
-
- residuesHash = me.icn3d.unionHash(residuesHash, me.icn3d.residues[resid]);
- }
+ residuesHash = me.icn3d.unionHash(residuesHash, me.icn3d.residues[resid]);
}
}
}
@@ -1149,17 +1141,21 @@ iCn3DUI.prototype = {
return residuesHash;
},
- pickCustomSphere: function (radius, nameArray) { var me = this; // me.icn3d.pAtom is set already
+ pickCustomSphere: function (radius, nameArray, nameArray2) { var me = this; // me.icn3d.pAtom is set already
// me.removeHlMenus();
- var select = "select zone cutoff " + radius + " | sets " + nameArray;
+ var select = "select zone cutoff " + radius + " | sets " + nameArray + " " + nameArray2;
var atomlistTarget = {}, otherAtoms = {};
- for(var i in me.icn3d.hAtoms) {
- atomlistTarget[i] = me.icn3d.atoms[i];
+ if(nameArray2[0] === 'selected') {
+ atomlistTarget = me.icn3d.hash2Atoms(me.icn3d.hAtoms);
+ }
+ else {
+ atomlistTarget = me.icn3d.hash2Atoms(me.getAtomsFromSets(nameArray2));
}
- if(nameArray.length == 0) { // select all hAtoms
+
+ if(nameArray.length == 0 || nameArray[0] === 'all') { // select all hAtoms
otherAtoms = me.icn3d.atoms;
}
else {
@@ -1215,17 +1211,31 @@ iCn3DUI.prototype = {
},
// between the highlighted and atoms in nameArray
- showHbonds: function (threshold, nameArray) { var me = this;
- me.icn3d.opts["hbonds"] = "yes";
- me.icn3d.opts["water"] = "dot";
+ showHbonds: function (threshold, nameArray, nameArray2, bSaltbridge) { var me = this;
+ var hbonds_saltbridge, select;
+ if(bSaltbridge !== undefined && bSaltbridge) {
+ hbonds_saltbridge = 'saltbridge';
+ select = 'salt bridge ' + threshold + ' | sets ' + nameArray + " " + nameArray2;
+ }
+ else {
+ hbonds_saltbridge = 'hbonds';
+ select = 'hbonds ' + threshold + ' | sets ' + nameArray + " " + nameArray2;
+ }
- var select = 'hbonds ' + threshold + ' | sets ' + nameArray;
+ me.icn3d.opts[hbonds_saltbridge] = "yes";
+ me.icn3d.opts["water"] = "dot";
- var complement = {};
+ var firstSetAtoms = {}, complement = {};
+ if(nameArray2[0] === 'selected') {
+ firstSetAtoms = me.icn3d.hash2Atoms(me.icn3d.hAtoms);
+ }
+ else {
+ firstSetAtoms = me.icn3d.hash2Atoms(me.getAtomsFromSets(nameArray2));
+ }
- if(nameArray.length == 0) {
+ if(nameArray.length == 0 || nameArray[0] === 'all') {
for(var i in me.icn3d.atoms) {
- if(!me.icn3d.hAtoms.hasOwnProperty(i) && me.icn3d.dAtoms.hasOwnProperty(i)) {
+ if(!firstSetAtoms.hasOwnProperty(i) && me.icn3d.dAtoms.hasOwnProperty(i)) {
complement[i] = me.icn3d.atoms[i];
}
}
@@ -1234,11 +1244,20 @@ iCn3DUI.prototype = {
complement = me.icn3d.hash2Atoms(me.getAtomsFromSets(nameArray));
}
- var firstAtom = me.icn3d.getFirstAtomObj(me.icn3d.hAtoms);
+ var firstAtom = me.icn3d.getFirstAtomObj(firstSetAtoms);
- if(Object.keys(complement).length > 0 && Object.keys(me.icn3d.hAtoms).length > 0) {
- var selectedAtoms = me.icn3d.calculateChemicalHbonds(complement, me.icn3d.intHash2Atoms(me.icn3d.dAtoms, me.icn3d.hAtoms), parseFloat(threshold) );
- me.resid2ResidhashHbond = me.icn3d.cloneHash(me.icn3d.resid2Residhash);
+ if(Object.keys(complement).length > 0 && Object.keys(firstSetAtoms).length > 0) {
+ var selectedAtoms = me.icn3d.calculateChemicalHbonds(complement, me.icn3d.intHash2Atoms(me.icn3d.dAtoms, firstSetAtoms), parseFloat(threshold), bSaltbridge );
+
+ var commanddesc;
+ if(bSaltbridge !== undefined && bSaltbridge) {
+ me.resid2ResidhashSaltbridge = me.icn3d.cloneHash(me.icn3d.resid2Residhash);
+ commanddesc = 'all atoms that have salt bridges with the selected atoms';
+ }
+ else {
+ me.resid2ResidhashHbond = me.icn3d.cloneHash(me.icn3d.resid2Residhash);
+ commanddesc = 'all atoms that are hydrogen-bonded with the selected atoms';
+ }
var residues = {}, atomArray = undefined;
@@ -1256,18 +1275,13 @@ iCn3DUI.prototype = {
}
}
- var commandname = 'hbonds_' + firstAtom.serial;
- var commanddesc = 'all atoms that are hydrogen-bonded with the selected atoms';
+ var commandname = hbonds_saltbridge + '_' + firstAtom.serial;
me.addCustomSelection(Object.keys(residues), commandname, commanddesc, select, true);
var nameArray = [commandname];
- //me.changeCustomResidues(nameArray);
-
me.saveSelectionIfSelected();
- //me.setStyle('sidec', 'ball and stick');
-
me.icn3d.draw();
}
},
@@ -1751,7 +1765,7 @@ iCn3DUI.prototype = {
}
}
- var text = '
' + cnt + ' hydrogen bond pairs:
Residue ID 1
Residue ID 2
';
+ var text = '
' + cnt + ' hydrogen bond pairs:
Atom 1
Atom 2
';
text += tmpText;
@@ -1761,48 +1775,41 @@ iCn3DUI.prototype = {
me.saveFile(file_pref + '_hbond_pairs.html', 'html', text);
},
- exportSpherePairs: function() { var me = this;
+ exportSaltbridgePairs: function() { var me = this;
var tmpText = '';
var cnt = 0;
- for(var resid1 in me.resid2ResidhashSphere) { // e.g., resid1: 1KQ2_A_6 ASN
- var resid1Final = resid1.substr(0, resid1.indexOf(' '));
-
- var caSerial1, caSerial2, tmpSerial;
- for(var serial in me.icn3d.residues[resid1Final]) {
- if(me.icn3d.calphas.hasOwnProperty(serial)) {
- caSerial1 = serial;
- break;
- }
- tmpSerial = serial;
+ for(var resid1 in me.resid2ResidhashSaltbridge) {
+ for(var resid2 in me.resid2ResidhashSaltbridge[resid1]) {
+ tmpText += '
' + resid1 + '
' + resid2 + '
';
+ ++cnt;
}
- if(caSerial1 === undefined) caSerial1 = tmpSerial;
+ }
- var ca1 = me.icn3d.atoms[caSerial1];
- var caVec1 = new THREE.Vector3(ca1.coord.x, ca1.coord.y, ca1.coord.z);
+ var text = '
' + cnt + ' Salt bridge pairs:
Atom 1
Atom 2
';
- for(var resid2 in me.resid2ResidhashSphere[resid1]) {
- var resid2Final = resid2.substr(0, resid2.indexOf(' '));
+ text += tmpText;
- for(var serial in me.icn3d.residues[resid2Final]) {
- if(me.icn3d.calphas.hasOwnProperty(serial)) {
- caSerial2 = serial;
- break;
- }
- tmpSerial = serial;
- }
- if(caSerial2 === undefined) caSerial2 = tmpSerial;
+ text += '
';
- var ca2 = me.icn3d.atoms[caSerial2];
- var caVec2 = new THREE.Vector3(ca2.coord.x, ca2.coord.y, ca2.coord.z);
+ var file_pref = (me.inputid) ? me.inputid : "custom";
+ me.saveFile(file_pref + '_saltbridge_pairs.html', 'html', text);
+ },
- var dist = caVec1.distanceTo(caVec2).toFixed(1);
+ exportSpherePairs: function() { var me = this;
+ var tmpText = '';
+ var cnt = 0;
+ for(var resid1 in me.resid2ResidhashSphere) { // e.g., resid1: 1KQ2_A_6_C ASN
+ for(var resid2 in me.resid2ResidhashSphere[resid1]) {
+ var dist = me.resid2ResidhashSphere[resid1][resid2];
tmpText += '
";
html += me.getRadio('mn6_hbonds', 'mn6_hbondsYes', 'Show');
html += me.getRadio('mn6_hbonds', 'mn6_hbondsNo', 'Hide', true);
html += "
";
html += "
";
+ html += "
Salt Bridge";
+ html += "
";
+ html += me.getRadio('mn6_saltbridge', 'mn6_saltbridgeYes', 'Show');
+ html += me.getRadio('mn6_saltbridge', 'mn6_saltbridgeNo', 'Hide', true);
+ html += "
";
+ html += "
";
+
html += me.getLink('mn2_aroundsphere2', 'Interactions');
html += "
Disulfide Bonds";
@@ -569,6 +576,7 @@ iCn3DUI.prototype.setMenu2b_base = function() { var me = this;
html += "
";
html += me.getRadio('mn6_addlabel', 'mn6_addlabelYes', 'by Picking Atoms');
html += me.getRadio('mn6_addlabel', 'mn6_addlabelSelection', 'per Selection');
+ html += me.getRadio('mn6_addlabel', 'mn6_addlabelAtoms', 'per Atom');
if(me.cfg.cid === undefined) {
html += me.getRadio('mn6_addlabel', 'mn6_addlabelResidues', 'per Residue');
html += me.getRadio('mn6_addlabel', 'mn6_addlabelChains', 'per Chain');
@@ -920,6 +928,7 @@ iCn3DUI.prototype.setMenu4_base = function() { var me = this;
html += "
";
html += me.getRadio('mn4_clr', 'mn4_clrSSGreen', 'Sheet in Green');
html += me.getRadio('mn4_clr', 'mn4_clrSSYellow', 'Sheet in Yellow');
+ html += me.getRadio('mn4_clr', 'mn4_clrSSSpectrum', 'Spectrum');
html += "
";
html += me.getRadio('mn4_clr', 'mn4_clrCharge', 'Charge');
@@ -1279,7 +1288,7 @@ iCn3DUI.prototype.setDialogs = function() { var me = this;
html += "";
html += "
";
- html += "MMDB ID: ";
+ html += "MMDB or PDB ID: ";
html += "";
html += "
";
@@ -1364,7 +1373,9 @@ iCn3DUI.prototype.setDialogs = function() { var me = this;
html += "";
html += "
";
- html += "
1. Make a selection in 3D, 2D or 1D whenever this window is open
";
+ html += "
1. Select the first set:
";
+ html += " ";
html += "
2. Threshold of H-bonds: Å
";
- html += "
3. Select sets to apply the H-bonds:
";
+ html += "
3. Select the second set to apply the H-bonds:
";
html += " ";
@@ -1385,6 +1396,30 @@ iCn3DUI.prototype.setDialogs = function() { var me = this;
html += "
H-bond pairs in a file
";
html += "
";
+ html += "
";
+ html += "
1. Select the first set:
";
+ html += " ";
+ html += "
2. Threshold of salt bridge: Å
";
+
+ html += "
3. Select the second set to apply the salt bridges:
";
+ html += " ";
+
+ html += "
4. salt bridges between current selection and the selected set
";
+ html += "
salt bridge pairs in a file
";
+ html += "
";
+
html += "
";
html += " Contour at:
";
html += "
";
- html += "
1. Make a selection in 3D, 2D or 1D whenever this window is open
";
+ html += "
1. Select the first set:
";
+ html += " ";
html += "
2. Sphere with a radius: Å
";
- html += "
3. Select sets to apply the sphere:
";
+ html += "
3. Select the second set to apply the sphere:
";
html += " ";
diff --git a/src/icn3dui/parsers/mmcif_mmdb_parser.js b/src/icn3dui/parsers/mmcif_mmdb_parser.js
index 6ba589b5..e43d8121 100644
--- a/src/icn3dui/parsers/mmcif_mmdb_parser.js
+++ b/src/icn3dui/parsers/mmcif_mmdb_parser.js
@@ -309,8 +309,10 @@ iCn3DUI.prototype.parseMmdbData = function (data, type) { var me = this;
var index = 1;
var chainNameHash = {};
for(var i in molid2rescount) {
- var color = '#' + ( '000000' + molid2rescount[i].color.toString( 16 ) ).slice( - 6 );
- var chainName = molid2rescount[i].chain.trim();
+ if(Object.keys(molid2rescount[i]).length === 0) continue;
+
+ var color = (molid2rescount[i].color === undefined) ? '#CCCCCC' : '#' + ( '000000' + molid2rescount[i].color.toString( 16 ) ).slice( - 6 );
+ var chainName = (molid2rescount[i].chain === undefined) ? '' : molid2rescount[i].chain.trim();
if(chainNameHash[chainName] === undefined) {
chainNameHash[chainName] = 1;
}
@@ -320,7 +322,6 @@ iCn3DUI.prototype.parseMmdbData = function (data, type) { var me = this;
var chainNameFinal = (chainNameHash[chainName] === 1) ? chainName : chainName + chainNameHash[chainName].toString();
var chain = id + '_' + chainNameFinal;
- //html += "