Skip to content

Commit

Permalink
Merge pull request #756 from prajwalkulkarni/refactor-ts-files-parser…
Browse files Browse the repository at this point in the history
…-utils

Refactor ts files parser utils
  • Loading branch information
dkoes authored Jan 26, 2024
2 parents 3c50910 + 57eb0a8 commit 8c3e9d4
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 119 deletions.
3 changes: 1 addition & 2 deletions src/parsers/MMTF.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ let mmtfHETATMtypes = new Set([
* @param ParserOptionsSpec
* @category Parsers
*/

export function MMTFparser(bindata: any, options: ParserOptionsSpec) {

var noH = !options.keepH; // suppress hydrogens by default
Expand Down Expand Up @@ -300,7 +299,7 @@ export function MMTFparser(bindata: any, options: ParserOptionsSpec) {
}

if (computeStruct && !ignoreStruct) {
computeSecondaryStructure(atoms, options.hbondCutoff);
computeSecondaryStructure(atoms as any, options.hbondCutoff);
}

return atoms;
Expand Down
2 changes: 1 addition & 1 deletion src/parsers/utils/anumToSymbol.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const anumToSymbol:any = {
export const anumToSymbol:Record<string, string> = {
1: 'H', 2: 'He',
3:'Li',4:'Be', 5: 'B', 6: 'C', 7:'N', 8:'O', 9:'F', 10: 'Ne',
11: 'Na',12:'Mg', 13: 'Al',14:'Si',15:'P',16:'S',17:'Cl',18:'Ar',
Expand Down
34 changes: 17 additions & 17 deletions src/parsers/utils/areConnected.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
import { AtomSpec } from "specs";
import { bondLength } from "./bondLength";

/*
* Return true if atom1 and atom2 are probably bonded to each other based on distance alone
*/

export function areConnected(atom1: { elem: any; x: number; y: number; z: number; altLoc: string; }, atom2: { elem: any; x: number; y: number; z: number; altLoc: string; }) {
var maxsq = bondLength(atom1.elem) + bondLength(atom2.elem);
*/
export function areConnected(atom1: AtomSpec, atom2: AtomSpec) {
let maxsq = bondLength(atom1.elem) + bondLength(atom2.elem);
maxsq += 0.25; // fudge factor, especially important for md frames, also see 1i3d
maxsq *= maxsq;

var xdiff = atom1.x - atom2.x;
let xdiff = atom1.x - atom2.x;
xdiff *= xdiff;
if (xdiff > maxsq) return false;
var ydiff = atom1.y - atom2.y;
let ydiff = atom1.y - atom2.y;
ydiff *= ydiff;
if (ydiff > maxsq) return false;
var zdiff = atom1.z - atom2.z;
let zdiff = atom1.z - atom2.z;
zdiff *= zdiff;
if (zdiff > maxsq) return false;

var distSquared = xdiff + ydiff + zdiff;
const distSquared = xdiff + ydiff + zdiff;

if (isNaN(distSquared)) return false;
else if (distSquared < 0.5) return false; // maybe duplicate position.
else if (distSquared > maxsq) return false;
else if (
atom1.altLoc != atom2.altLoc &&
atom1.altLoc != " " &&
atom2.altLoc != " "
if (
isNaN(distSquared) ||
distSquared < 0.5 ||
distSquared > maxsq ||
(atom1.altLoc !== atom2.altLoc && atom1.altLoc !== " " && atom2.altLoc !== " ")
)
return false; // don't connect across alternate locations
else return true;
return false;


return true;
}
28 changes: 17 additions & 11 deletions src/parsers/utils/assignBackboneHBonds.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
// This will identify all hydrogen bonds between backbone
// atoms; assume atom names are correct, only identifies
// single closest hbond
export function assignBackboneHBonds(atomsarray: string | any[], hbondCutoff: number) {
let maxlength = hbondCutoff || 3.2;
let maxlengthSq = maxlength*maxlength;
let atoms = [];

import { AtomSpec } from "specs";
// interface Atoms {index: number; atom: string; hbondDistanceSq: number; hbondOther: any; hetflag:any}
export function assignBackboneHBonds(
atomsarray: Array<AtomSpec>,
hbondCutoff: number
) {
const maxlength = hbondCutoff || 3.2;
const maxlengthSq = maxlength * maxlength;
const atoms = [];

for (let i = 0, n = atomsarray.length; i < n; i++) {
atomsarray[i].index = i;
// only consider 'N' and 'O'
var atom = atomsarray[i];
const atom = atomsarray[i];
if (!atom.hetflag && (atom.atom === "N" || atom.atom === "O")) {
atoms.push(atom);
atom.hbondOther = null;
Expand All @@ -21,20 +27,20 @@ export function assignBackboneHBonds(atomsarray: string | any[], hbondCutoff: nu
return a.z - b.z;
});
for (let i = 0, n = atoms.length; i < n; i++) {
var ai = atoms[i];
const ai = atoms[i];

for (let j = i + 1; j < n; j++) {
var aj = atoms[j];
var zdiff = aj.z - ai.z;
const aj = atoms[j];
const zdiff = aj.z - ai.z;
if (zdiff > maxlength)
// can't be connected
break;
if (aj.atom == ai.atom) continue; // can't be connected, but later might be
var ydiff = Math.abs(aj.y - ai.y);
const ydiff = Math.abs(aj.y - ai.y);
if (ydiff > maxlength) continue;
var xdiff = Math.abs(aj.x - ai.x);
const xdiff = Math.abs(aj.x - ai.x);
if (xdiff > maxlength) continue;
var dist = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff;
const dist = xdiff * xdiff + ydiff * ydiff + zdiff * zdiff;
if (dist > maxlengthSq) continue;

if (aj.chain == ai.chain && Math.abs(aj.resi - ai.resi) < 4) continue; // ignore bonds between too close residues
Expand Down
89 changes: 46 additions & 43 deletions src/parsers/utils/assignBonds.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,40 @@
import { AtomSpec } from "specs";
import { areConnected } from "./areConnected";

/**
* @param {AtomSpec[]} atoms
*/
*/
const OFFSETS = [
{ x: 0, y: 0, z: 1 },
{ x: 0, y: 1, z: -1 },
{ x: 0, y: 1, z: 0 },
{ x: 0, y: 1, z: 1 },
{ x: 1, y: -1, z: -1 },
{ x: 1, y: -1, z: 0 },
{ x: 1, y: -1, z: 1 },
{ x: 1, y: 0, z: -1 },
{ x: 1, y: 0, z: 0 },
{ x: 1, y: 0, z: 1 },
{ x: 1, y: 1, z: -1 },
{ x: 1, y: 1, z: 0 },
{ x: 1, y: 1, z: 1 },
];
const MAX_BOND_LENGTH = 4.95; // (largest bond length, Cs) 2.25 * 2 * 1.1 (fudge factor)

export function assignBonds(atoms: string | any[]) {
// Assign bonds - yuck, can't count on connect records

for (var i = 0, n = atoms.length; i < n; i++) {
for (let i = 0, n = atoms.length; i < n; i++) {
// Don't reindex if atoms are already indexed
if (!atoms[i].index) atoms[i].index = i;
}

var grid = {};
var MAX_BOND_LENGTH = 4.95; // (largest bond length, Cs) 2.25 * 2 * 1.1 (fudge factor)

for (var index = 0; index < atoms.length; index++) {
var atom = atoms[index];
var x = Math.floor(atom.x / MAX_BOND_LENGTH);
var y = Math.floor(atom.y / MAX_BOND_LENGTH);
var z = Math.floor(atom.z / MAX_BOND_LENGTH);
const grid = {};
for (let index = 0; index < atoms.length; index++) {
const atom = atoms[index];
const x = Math.floor(atom.x / MAX_BOND_LENGTH);
const y = Math.floor(atom.y / MAX_BOND_LENGTH);
const z = Math.floor(atom.z / MAX_BOND_LENGTH);
if (!grid[x]) {
grid[x] = {};
}
Expand All @@ -33,25 +48,28 @@ export function assignBonds(atoms: string | any[]) {
grid[x][y][z].push(atom);
}

var findConnections = function (points: string | any[], otherPoints: string | any[]) {
for (var i = 0; i < points.length; i++) {
var atom1 = points[i];
for (var j = 0; j < otherPoints.length; j++) {
var atom2 = otherPoints[j];
function findConnections(
points: Array<AtomSpec>,
otherPoints: Array<AtomSpec>
) {
for (let i = 0; i < points.length; i++) {
const atom1 = points[i];
for (let j = 0; j < otherPoints.length; j++) {
const atom2 = otherPoints[j];

if (areConnected(atom1, atom2)) {
//gracefully handle one-sided bonds
var a2i = atom1.bonds.indexOf(atom2.index);
var a1i = atom2.bonds.indexOf(atom1.index);
if (a2i == -1 && a1i == -1) {
const a2i = atom1.bonds.indexOf(atom2.index);
const a1i = atom2.bonds.indexOf(atom1.index);
if (a2i === -1 && a1i === -1) {
atom1.bonds.push(atom2.index);
atom1.bondOrder.push(1);
atom2.bonds.push(atom1.index);
atom2.bondOrder.push(1);
} else if (a2i == -1) {
} else if (a2i === -1) {
atom1.bonds.push(atom2.index);
atom1.bondOrder.push(atom2.bondOrder[a1i]);
} else if (a1i == -1) {
} else if (a1i === -1) {
atom2.bonds.push(atom1.index);
atom2.bondOrder.push(atom1.bondOrder[a2i]);
}
Expand All @@ -60,33 +78,18 @@ export function assignBonds(atoms: string | any[]) {
}
};

/*const*/ var OFFSETS = [
{ x: 0, y: 0, z: 1 },
{ x: 0, y: 1, z: -1 },
{ x: 0, y: 1, z: 0 },
{ x: 0, y: 1, z: 1 },
{ x: 1, y: -1, z: -1 },
{ x: 1, y: -1, z: 0 },
{ x: 1, y: -1, z: 1 },
{ x: 1, y: 0, z: -1 },
{ x: 1, y: 0, z: 0 },
{ x: 1, y: 0, z: 1 },
{ x: 1, y: 1, z: -1 },
{ x: 1, y: 1, z: 0 },
{ x: 1, y: 1, z: 1 },
];
for (let xg in grid) {
let x = parseInt(xg);
const x = parseInt(xg);
for (let yg in grid[x]) {
let y = parseInt(yg);
const y = parseInt(yg);
for (let zg in grid[x][y]) {
let z = parseInt(zg);
let points = grid[x][y][z];
const z = parseInt(zg);
const points = grid[x][y][z];

for (let i = 0; i < points.length; i++) {
let atom1 = points[i];
const atom1 = points[i];
for (let j = i + 1; j < points.length; j++) {
let atom2 = points[j];
const atom2 = points[j];
if (areConnected(atom1, atom2)) {
if (atom1.bonds.indexOf(atom2.index) == -1) {
atom1.bonds.push(atom2.index);
Expand All @@ -99,15 +102,15 @@ export function assignBonds(atoms: string | any[]) {
}

for (let o = 0; o < OFFSETS.length; o++) {
let offset = OFFSETS[o];
const offset = OFFSETS[o];
if (
!grid[x + offset.x] ||
!grid[x + offset.x][y + offset.y] ||
!grid[x + offset.x][y + offset.y][z + offset.z]
)
continue;

let otherPoints = grid[x + offset.x][y + offset.y][z + offset.z];
const otherPoints = grid[x + offset.x][y + offset.y][z + offset.z];
findConnections(points, otherPoints);
}
}
Expand Down
40 changes: 24 additions & 16 deletions src/parsers/utils/atomNameToElem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,31 @@ import { bondTable } from "./bondLength";

// Attempts to infer atomic element from an atom name
export function atomNameToElem(name: string, nothetero: boolean) {
var elem = name.replace(/ /g, "");
if(elem.length > 0 && elem[0] == 'H' && elem != 'Hg' && elem != 'He' && elem != 'Hf' && elem != 'Hs' && elem != 'Ho') {
elem = 'H'; //workaround weird hydrogen names from MD, note mercury must use lowercase
let elem = name.replace(/ /g, "");
if (
elem.length > 0 &&
elem[0] === "H" &&
elem !== "Hg" &&
elem !== "He" &&
elem !== "Hf" &&
elem !== "Hs" &&
elem !== "Ho"
) {
elem = "H"; //workaround weird hydrogen names from MD, note mercury must use lowercase
}
if(elem.length > 1) {
elem = elem[0].toUpperCase() + elem.substring(1).toLowerCase();
if(typeof(bondTable[elem]) === 'undefined') {
//not a known element, probably should just use first letter
elem = elem[0];
} else if(nothetero) {
if(elem == 'Ca') { //alpha carbon, not calcium
elem = 'C';
}
else if(elem == 'Cd') {
elem = 'C';
}
if (elem.length > 1) {
elem = elem[0].toUpperCase() + elem.substring(1).toLowerCase();
if (bondTable[elem] === undefined) {
//not a known element, probably should just use first letter
elem = elem[0];
} else if (nothetero) {
if (elem === "Ca") {
//alpha carbon, not calcium
elem = "C";
} else if (elem === "Cd") {
elem = "C";
}
}
}
return elem;
};
}
11 changes: 4 additions & 7 deletions src/parsers/utils/bondLength.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@

// Covalent radii lookup table used to identify bonds in assignBonds
export let bondTable:any = {
export let bondTable: Record<string, number> = {
H :0.37, He:0.32,
Li:1.34,Be:0.90, B :0.82,C :0.77,N :0.75,O :0.73,F :0.71,Ne:0.69,
Na:1.54,Mg:1.30, Al:1.18,Si:1.11,P :1.06,S :1.02,Cl:0.99,Ar:0.97,
Expand All @@ -11,15 +10,13 @@ export let bondTable:any = {
// None of the bottom row or any of the Lanthanides have bond lengths
};


// Get the length used for bond identification for the specified element.
export function bondLength(elem: string | number) {
return bondTable[elem] || 1.6;
};
}

// Set the length used for bond identification for the specified element.
export function setBondLength(elem:string, radius:number) {
if(radius < 0) radius = 0;
export function setBondLength(elem: string, radius: number) {
if (radius < 0) radius = 0;
bondTable[elem] = radius;
}

Loading

0 comments on commit 8c3e9d4

Please sign in to comment.