Skip to content

Commit

Permalink
Merge branch 'local_3dmol'
Browse files Browse the repository at this point in the history
  • Loading branch information
Rasic2 committed Jul 20, 2024
2 parents 848a366 + c77554e commit ce62c30
Show file tree
Hide file tree
Showing 288 changed files with 5,387 additions and 229 deletions.
225 changes: 111 additions & 114 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "3dmol",
"version": "2.1.0",
"version": "2.2.1post1",
"description": "JavaScript/TypeScript molecular visualization library",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion py3Dmol/py3Dmol/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class view(object):
the exception that the functions all return None.
http://3dmol.org/doc/GLViewer.html
'''
def __init__(self,query='',width=640,height=480,viewergrid=None,data=None,style=None,linked=True,options=dict(),format=None,js='https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.1.0/3Dmol-min.js'):
def __init__(self,query='',width=640,height=480,viewergrid=None,data=None,style=None,linked=True,options=dict(),format=None,js='https://cdnjs.cloudflare.com/ajax/libs/3Dmol/2.2.1-post1/3Dmol-min.js'):
'''Create a 3Dmol.js view.
width -- width in pixels of container
height -- height in pixels of container
Expand Down
2 changes: 1 addition & 1 deletion py3Dmol/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
# the version across setup.py and the project code, see
# https://packaging.python.org/en/latest/single_source_version.html
# Keep version in synce with 3Dmol.js version. Use "postX" suffix if needed
version='2.1.0',
version='2.2.1',

description='An IPython interface for embedding 3Dmol.js views in Jupyter notebooks',
long_description=long_description,
Expand Down
2 changes: 1 addition & 1 deletion src/GLModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2836,7 +2836,7 @@ export class GLModel {
console.log("Unknown format: " + format);
// try to guess correct format from data contents
if (data instanceof Uint8Array) {
format = "mmtf"; //currently only supported binary format?
format = "bcif"; //mmtf deprecated so go with bcif
} else if ((data as string).match(/^@<TRIPOS>MOLECULE/gm)) {
format = "mol2";
} else if ((data as string).match(/^data_/gm) && (data as string).match(/^loop_/gm)) {
Expand Down
15 changes: 14 additions & 1 deletion src/GLViewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export class GLViewer {
private longTouchTimeout: any;

private divwatcher: any;
private intwatcher: any;
private spinInterval: any;


Expand Down Expand Up @@ -651,6 +652,19 @@ export class GLViewer {
this.divwatcher.observe(this.container);
}

if (typeof (window.IntersectionObserver) !== "undefined") {
//make sure a viewer that is becoming visible is alive
let intcallback = (entries, observer) => {
entries.forEach((entry) => {
if(entry.isIntersecting) {
this.resize();
}
});
};
this.intwatcher = new window.IntersectionObserver(intcallback);
this.intwatcher.observe(this.container);
}

try {
if (typeof (this.callback) === "function")
this.callback(this);
Expand Down Expand Up @@ -1373,7 +1387,6 @@ export class GLViewer {
} else if (this.animated) {
this._viewer.resumeAnimate();
}

this.updateSize();

if (regen) { //restored rendere, need to regenerate scene
Expand Down
8 changes: 4 additions & 4 deletions src/autoload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export function autoload(viewer?: any, callback?: (arg0: any) => void) {
viewerdiv.dataset[datatypes[datatypes.length - 1]] = molName;
}

var divdata = viewerdiv.dataset;
let divdata = viewerdiv.dataset;
for (i in divdata) {
if ((i.substring(0, 3) === "pdb" && (i !== "pdb"))) {
datauri.push("https://files.rcsb.org/view/" + divdata[i] + ".pdb");
Expand Down Expand Up @@ -187,7 +187,7 @@ export function autoload(viewer?: any, callback?: (arg0: any) => void) {
}
};

var glviewer = viewer;
let glviewer = viewer;
try {
var config: any = specStringToObject(viewerdiv.dataset.config) || {};
if (config.backgroundColor === undefined) config.backgroundColor = bgcolor;
Expand All @@ -213,7 +213,7 @@ export function autoload(viewer?: any, callback?: (arg0: any) => void) {
if (datauri.length != 0) {
//load multiple data elements in serial
let i = 0;
var process = function (moldata: any) {
let process = ((viewerdiv, glviewer) => function (moldata: any) {
//add moldata to viewer and load next model
uri = datauri[i]; //this is where the moldata came from
var type = viewerdiv.dataset.type || viewerdiv.dataset.datatype || datatypes[i];
Expand All @@ -240,7 +240,7 @@ export function autoload(viewer?: any, callback?: (arg0: any) => void) {
processing_autoinit = false;
if (callback) callback(glviewer);
}
};
})(viewerdiv,glviewer);
get(datauri[0]).then(process);

}
Expand Down
196 changes: 177 additions & 19 deletions src/parsers/BCIF.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,145 @@ import { isEmpty } from "./utils/isEmpty";
declare var MMTF: MMTFobj;


class Connectivity {
C: Record<string, Record<string, Record<string, number>>> = {};

constructor(comp_bond) {
if (comp_bond) {
let ids = comp_bond.getField('comp_id');
let a1s = comp_bond.getField('atom_id_1');
let a2s = comp_bond.getField('atom_id_2');
let orders = comp_bond.getField('value_order');

for (let i = 0; i < ids.length; i++) {
let resn = ids[i];
let a1 = a1s[i];
let a2 = a2s[i];
let oname = orders[i];
let o = 1;
if (oname == 'doub') o = 2;
else if (oname == 'trip') o = 3;

if (this.C[resn] == undefined) {
this.C[resn] = {};
}
if (this.C[resn][a1] == undefined) {
this.C[resn][a1] = {};
}
if (this.C[resn][a2] == undefined) {
this.C[resn][a2] = {};
}
this.C[resn][a1][a2] = o;
this.C[resn][a2][a1] = o;
}
}
}

//returns bond order, zero if not connected
order(resn: string, atom1: string, atom2: string): number {
if (this.C[resn] !== undefined) {
if (this.C[resn][atom1] !== undefined) {
if (this.C[resn][atom1][atom2] !== undefined) {
return this.C[resn][atom1][atom2];
}
}
}
return 0;
}
}

/* Class for recording inter-component connectivity */
class StructConn {
public C: [[string,number,string,string],[string,number,string,string],number][] = []; //chain,resi,resn,atomn

constructor(struct_conn) {
if(struct_conn) {
//have no idea what the deal with with ptnr3..
let types = struct_conn.getField('conn_type_id');
let chain1 = struct_conn.getField('ptnr1_label_asym_id');
let resi1 = struct_conn.getField('ptnr1_label_seq_id');
let resn1 = struct_conn.getField('ptnr1_label_comp_id');
let a1 = struct_conn.getField('ptnr1_label_atom_id');
let chain2 = struct_conn.getField('ptnr2_label_asym_id');
let resi2 = struct_conn.getField('ptnr2_label_seq_id');
let resn2 = struct_conn.getField('ptnr2_label_comp_id');
let a2 = struct_conn.getField('ptnr2_label_atom_id');
let bo = struct_conn.getField('pdbx_value_order');

for(let i = 0; i < types.length; i++) {
if(types[i] == 'disulf' || types[i] == 'covale') { //metal too?
let o = bo ? (bo[i] == "" ? 1: parseInt(bo[i])) : 1;
this.C.push([[chain1[i],resi1[i],resn1[i],a1[i]],[chain2[i],resi2[i],resn2[i],a2[i]],o]);
}
}

}
}
}

/* group atoms by chain/resid */
class Residues {
R: Record<string, Record<number, Record<string, Array<AtomSpec>>>> = {}; //chain, resid, resn (redundant), atom list
constructor() {

}

add(a: AtomSpec) {
if (this.R[a.lchain] == undefined) this.R[a.lchain] = {};
if (this.R[a.lchain][a.lresi] == undefined) this.R[a.lchain][a.lresi] = {};
if (this.R[a.lchain][a.lresi][a.lresn] == undefined) this.R[a.lchain][a.lresi][a.lresn] = [];
this.R[a.lchain][a.lresi][a.lresn].push(a);
this.R[a.lchain][a.lresi][a.lresn][a.atom] = a; //look up by atom name
}

private geta([ch,resi,resn,aname]: [string,number,string,string]) {
if(this.R[ch] !== undefined &&
this.R[ch][resi] !== undefined &&
this.R[ch][resi][resn] !== undefined) {
return this.R[ch][resi][resn][aname];
}
return undefined;
}

setBonds(C: Connectivity, SC: StructConn) {
for(let ch in this.R) {
for(let resi in this.R[ch]) {
for(let resn in this.R[ch][resi]) {
let atoms = this.R[ch][resi][resn];
for(let i = 0; i < atoms.length; i++) {
for(let j = i+1; j < atoms.length; j++) {
let a1 = atoms[i];
let a2 = atoms[j];
let bo = C.order(resn,a1.atom,a2.atom);
if(bo > 0) {
a1.bonds.push(a2.index);
a2.bonds.push(a1.index);
a1.bondOrder.push(bo);
a2.bondOrder.push(bo);
}
}
}
}
}
}

for(let conn of SC.C) {
let a1 = conn[0];
let a2 = conn[1];
let bo = conn[2];
let atom1 = this.geta(a1);
let atom2 = this.geta(a2);
if(atom1 != undefined && atom2 != undefined) {
atom1.bonds.push(atom2.index);
atom2.bonds.push(atom1.index);
atom1.bondOrder.push(bo);
atom2.bondOrder.push(bo);
}
}

}
}


/**
* @param bindata - binary UInt8Array buffer or a base64 encoded string
Expand All @@ -22,7 +161,7 @@ declare var MMTF: MMTFobj;
export function BCIF(bindata: any, options: ParserOptionsSpec) {

var noH = !options.keepH; // suppress hydrogens by default
//var selAltLoc = options.altLoc ? options.altLoc : 'A'; //default alternate location to select if present
var selAltLoc = options.altLoc ? options.altLoc : 'A'; //default alternate location to select if present
var computeStruct = !options.noComputeSecondaryStructure;
//var assemblyIndex = options.assemblyIndex ? options.assemblyIndex : 0;
const noAssembly = !options.doAssembly; // don't assemble by default
Expand Down Expand Up @@ -59,10 +198,10 @@ export function BCIF(bindata: any, options: ParserOptionsSpec) {



//loop over models,
//loop over models
for (let m = 0; m < numModels; m++) {

const serialToIndex: number[] = []; // map from pdb serial to index in atoms
let startm = atoms.length;
const serialToIndex: [number, number][] = []; // map from pdb serial to index in atoms
modelData.push({ symmetries: [] });
atoms.push([]);

Expand Down Expand Up @@ -158,8 +297,13 @@ export function BCIF(bindata: any, options: ParserOptionsSpec) {
modelData[modelData.length - 1].symmetries.push(matrix);
}
}
//atom info

//extract connectivity information
let connect = new Connectivity(cats.chem_comp_bond);
let residues = new Residues();
let sconnect = new StructConn(cats.struct_conn);

//atom info
let asites = cats.atom_site;
let atomCount = asites.rowCount;
let group_pdb = asites.getField('group_PDB')
Expand Down Expand Up @@ -192,7 +336,10 @@ export function BCIF(bindata: any, options: ParserOptionsSpec) {
if (options.multimodel) {
if (!options.onemol) {
atoms.push([]);
modelData.push(modelData[modelData.length-1]);
modelData.push(modelData[modelData.length - 1]);
curmodel = modelnums[i];
residues.setBonds(connect, sconnect);
residues = new Residues();
}
} else {
break; //first model only
Expand Down Expand Up @@ -225,13 +372,15 @@ export function BCIF(bindata: any, options: ParserOptionsSpec) {
: label_comp_id
? label_comp_id[i].trim()
: undefined;
atom.lresn = label_comp_id ? label_comp_id[i].trim() : undefined;
atom.atom = auth_atom_id
? auth_atom_id[i].replace(/"/gm, "")
: label_atom_id
? label_atom_id[i].replace(/"/gm, "")
: undefined; //"primed" names are in quotes

atom.icode = icodes ? icodes[i] : undefined;
atom.altLoc = atom.icode;
atom.hetflag =
!group_pdb ||
group_pdb[i] === "HETA" ||
Expand All @@ -244,32 +393,41 @@ export function BCIF(bindata: any, options: ParserOptionsSpec) {
atom.elem = elem[0].toUpperCase() + elem.substring(1, 2).toLowerCase();
if (bfactors) atom.b = bfactors[i];

if(noH && atom.elem == 'H') {
if (noH && atom.elem == 'H') {
continue;
}
if (atom.altLoc != '' && atom.altLoc != selAltLoc && selAltLoc != '*') {
continue;
}

atom.bonds = [];
atom.ss = "c";
atom.serial = serials[i];
serialToIndex[atom.serial] = i;
atom.model = curmodel;
atom.bondOrder = [];
atom.properties = {};
atom.index = atoms[atoms.length - 1].length;
serialToIndex[atom.serial] = [atoms.length, atom.index];
atoms[atoms.length - 1].push(atom);
}
residues.add(atom);

}

residues.setBonds(connect, sconnect);
// Assign secondary structures from pdb file
if (!isEmpty(sslookup)) {
let matoms = atoms[atoms.length - 1];
for (let i = 0; i < matoms.length; i++) {
const atom = matoms[i];
if (atom === undefined) continue;
if (atom.lchain in sslookup && atom.lresi in sslookup[atom.lchain]) {
const code = sslookup[atom.lchain][atom.lresi];
atom.ss = code[0];
if (code.length > 1) {
if (code[1] == "1") atom.ssbegin = true;
else if (code[1] == "2") atom.ssend = true;
for (let mi = startm; mi < atoms.length; mi++) {
let matoms = atoms[mi];
for (let i = 0; i < matoms.length; i++) {
const atom = matoms[i];
if (atom === undefined) continue;
if (atom.lchain in sslookup && atom.lresi in sslookup[atom.lchain]) {
const code = sslookup[atom.lchain][atom.lresi];
atom.ss = code[0];
if (code.length > 1) {
if (code[1] == "1") atom.ssbegin = true;
else if (code[1] == "2") atom.ssend = true;
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/parsers/CIF.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,9 @@ export function CIF(str: string, options: ParserOptionsSpec = {}) {
!mmCIF._atom_site_group_pdb ||
mmCIF._atom_site_group_pdb[i] === "HETA" ||
mmCIF._atom_site_group_pdb[i] === "HETATM";
if(mmCIF._atom_site_b_iso_or_equiv ) {
atom.b = parseFloat(mmCIF._atom_site_b_iso_or_equiv[i]);
}
let elem = "X";
if (mmCIF._atom_site_type_symbol) {
elem = mmCIF._atom_site_type_symbol[i].replace(/\(?\+?\d+.*/, "");
Expand Down
Loading

0 comments on commit ce62c30

Please sign in to comment.