Closed JavierSanchez-Utges closed 6 months ago
When you load the files, set the assignBonds
parser option to false.
But then I am losing ALL bonds, not just the wrong ones, it seems. As I get nothing when I am showing sticks.
Is it on here I have to add it: let model = viewer.addModel(data, "cif", {assignBonds: false,}); // Load data
?
It seems bonds
does not only consider covalent bonds, but other kinds of interactions? The Mn and Zn atoms here satisfy {not:{bonds:0}}
, and so do present bonds. In purple are HETATM that present bonds, and yellow HETATM that do not present any bonds.
Basically what I want to do is select all ions and HOH and show them independently as spheres, and molecules showing covalent bonds, and formed by multiple atoms, such as other ligands, show them with sticks.
Here my code:
<title>3DMol.js experiment</title>
<script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
<script src="https://3Dmol.org/build/3Dmol-min.js"></script>
<script src="https://3Dmol.org/build/3Dmol.ui-min.js"></script>
<div id="container-01" class="mol-container"></div>
<style>
.mol-container {
width: 50%;
height: 75%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: px solid black; /* Adds a black border */
box-sizing: border-box; /* Ensures that the border is included in the element's total width and height */
}
</style>
<script>
let element = document.querySelector('#container-01');
let config = { backgroundColor: 'white', keepH: false };
let viewer = $3Dmol.createViewer(element, config);
let pdbUris = [
'/static/data/Q9UGL1/5fze_updated.cif',
];
let loadedCount = 0; // Counter for loaded structures
let models = [];
let modelOrder = {}; // creating dictionary to save the order in which files get loaded
pdbUris.forEach(pdbUri => {
jQuery.ajax(pdbUri, {
success: function(data) {
let model = viewer.addModel(data, "cif"); // Load data
console.log("Loaded model", pdbUri, model.getID(), loadedCount);
modelOrder[pdbUri] = model.getID();
models.push(model);
loadedCount++; // Increment counter
if (loadedCount === pdbUris.length) { // All structures are loaded, apply styles
console.log("All structures loaded");
console.log("Model order", modelOrder);
viewer.setViewStyle({style:"outline", width:0.0625, color:"black"});
viewer.setStyle({hetflag: false}, {cartoon: {hidden: false, style: 'oval', color: 'white', arrows: true,}});
viewer.setStyle({hetflag: true}, {stick: {hidden: true}});
viewer.setStyle({and:[{hetflag: true}, {not:{bonds:0}}]}, {sphere: {hidden: false, color: 'purple', radius: 0.5}});
viewer.setStyle({and:[{hetflag: true}, {bonds:0}]}, {sphere: {hidden: false, color: 'gold', radius: 0.5}});
viewer.zoomTo();
viewer.render();
}
},
error: function(hdr, status, err) {
console.error("Failed to load PDB " + pdbUri + ": " + err);
// Error handling, potentially increment loadedCount or handle differently
},
});
});
</script>
A properly constructed cif file will specify the bonds of hetatms. Lacking bond information in the file, the bonds must be inferred using distances (and possibly valency constraints). If you can provide 5fze_updated.cif I can see if there's a way to tweak the heuristics to get a better result, but most likely you will want to select and style ions separately.
Here I am using 5FPU_updated as downloaded from PDBe, which was the structure in which the MN ion was incorrectly linked to the K0I ligand molecule.
Here the code:
<title>3DMol.js experiment</title>
<script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
<script src="https://3Dmol.org/build/3Dmol-min.js"></script>
<script src="https://3Dmol.org/build/3Dmol.ui-min.js"></script>
<div id="container-01" class="mol-container"></div>
<style>
.mol-container {
width: 50%;
height: 75%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: px solid black; /* Adds a black border */
box-sizing: border-box; /* Ensures that the border is included in the element's total width and height */
}
</style>
<script>
let element = document.querySelector('#container-01');
let config = { backgroundColor: 'white', keepH: false };
let viewer = $3Dmol.createViewer(element, config);
let pdbUris = [
<!-- '/static/data/Q9UGL1/5fpu_A_trans.cif', -->
'/static/data/Q9UGL1/5fpu_updated.cif',
<!-- '/static/data/Q9UGL1/5fv3_A_trans.cif', -->
<!-- '/static/data/Q9UGL1/6ej1_A_trans.cif', -->
];
let loadedCount = 0; // Counter for loaded structures
let models = [];
let modelOrder = {}; // creating dictionary to save the order in which files get loaded
let modelOrderRev = {};
pdbUris.forEach(pdbUri => {
jQuery.ajax(pdbUri, {
success: function(data) {
let model = viewer.addModel(data, "cif",); // Load data
let modelID = model.getID();
let pdbID = pdbUri.split("/").pop().split("_")[0];
modelOrder[pdbUri] = modelID;
modelOrderRev[modelID] = pdbID;
models.push(model);
loadedCount++; // Increment counter
if (loadedCount === pdbUris.length) { // All structures are loaded, apply styles
console.log("All structures loaded");
viewer.setViewStyle({style:"outline", width:0.0625, color:"black"});
viewer.setStyle({hetflag: false}, {cartoon: {hidden: false, style: 'oval', color: 'white', arrows: true, thickness: 0.25}});
viewer.setStyle({hetflag: true}, {stick: {hidden: true, radius: 0.25}});
viewer.addStyle({and:[{hetflag: true}, {not:{resn: "HOH"}}]}, {stick: {hidden: false, color: "blue", radius: 0.25}});
viewer.addStyle({and:[{hetflag: true}, {not:{resn: "HOH"}}]}, {sphere: {hidden: false, color: "red", radius: 0.20}});
viewer.addStyle({resn: "HOH"}, {sphere: {hidden: false, color: "gold", radius: 0.20}});
viewer.addStyle({resn: 'MN'}, {stick: {hidden: false, radius: 0.25, color:"orange"}});
viewer.setHoverable({}, true,
function(atom,viewer,event,container) {
if(!atom.label) {
atom.label = viewer.addLabel(
modelOrderRev[atom.model] + " " + atom.chain + " " + atom.resn + " " + atom.resi + " " + atom.atom,
{position: atom, backgroundColor: 'mintcream', fontColor:'black', borderColor: 'black', borderThickness: 2}
);
}
},
function(atom) {
if(atom.label) {
viewer.removeLabel(atom.label);
delete atom.label;
}
}
);
viewer.zoomTo();
viewer.render();
}
},
error: function(hdr, status, err) {
console.error("Failed to load PDB " + pdbUri + ": " + err);
// Error handling, potentially increment loadedCount or handle differently
},
});
});
</script>
Here the files: 5fpu_A_trans.txt 5fpu_updated.txt
Loading the structure with default settings seems to draw bond between K0I and MN. Using {assignBonds: false}
does not draw any bonds at all and nothing can be displayed with sticks.
The reason there is a bond is that the atoms are within their covalent radius of each other. I was wondering why pymol doesn't draw a bond and it is because there is an unbound_cations option (on by default in pymol) that avoids such bonds. I've added a parser option, unboundCations
that, if set, will mimic this behavior.
https://3dmol.org/tests/auto/generate_test.cgi?test=unboundcations
I see, very interesting. That works nicely now, all the bonds between HOH, MN and the other ligands are gone now. I also really like the touch that the opacity adds to the visualisation.
I found the PyMol code and saw it considers the same cations you implemented: ["Na", "K", "Ca", "Mg", "Mn", "Sr"]
. I was wondering then, why is PyMol just implementing these? I get they are some of the most common, but why isn't Zinc included for example. And what about anions? Chemistry is not my area of expertise, and I might be missing something here.
I also had a question about your implementation:
What is the meaning of this line var callback = function() {};
and then calling the function at the end when rendering the new viewer viewer.render(callback);
.
That is something the test harness uses (e.g., when this individual test is run with glcheck on the commandline or in browser at https://3dmol.org/tests/). We need a callback to capture the input and compare it to the reference image (and to know to proceed to the next test).
Describe the bug
I think bonds are being drawn between atoms that should not be connected. For example, the O atoms from
HOH
andMN
of the Mn ions are being linked to theB7Q
(blue),K0I
(red), andW77
(cyan).To Reproduce
Expected behaviour
Only atoms forming part of the same molecule are connected by bonds drawn in the viewer. In this case, O atoms of
HOH
and Mn ofMN
are not connected to the other ligands.I suspect this has to do with
assignPDBBonds
(https://3dmol.csb.pitt.edu/doc/parsers_utils_assignPDBBonds.ts.html), andassignBonds
(https://3dmol.csb.pitt.edu/doc/parsers_utils_assignBonds.ts.html), which seems they use distance, amongst other things to draw the bonds.I understand the connectivity issue is a tricky one to solve, but, perhaps looking at the
resn
orresi
might fix drawing incorrect bonds between different molecules (that satisfy the distance criteria). Just a suggestion, this simplistic solution might not be adequate, though.Screenshots (3DMol.js on the left and ChimeraX on the right)
Desktop
Additional context
Here the files:
5fpu_A_trans.txt 5fv3_A_trans.txt 6ej1_A_trans.txt