-
Notifications
You must be signed in to change notification settings - Fork 5
/
index.js
85 lines (78 loc) · 2.76 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
const ATOM_NAME = 'ATOM ';
const RESIDUE_NAME = 'SEQRES';
/**
* Parses the given PDB string into json
* @param {String} pdb
* @returns {Object}
*/
module.exports = function parsePdb(pdb) {
const pdbLines = pdb.split('\n');
const atoms = [];
const seqRes = []; // raw SEQRES entry data
let residues = []; // individual residue data parsed from SEQRES
const chains = new Map(); // individual rchaindata parsed from SEQRES
// Iterate each line looking for atoms
pdbLines.forEach((pdbLine) => {
if (pdbLine.substr(0, 6) === ATOM_NAME) {
// http://www.wwpdb.org/documentation/file-format-content/format33/sect9.html#ATOM
atoms.push({
serial: parseInt(pdbLine.substring(6, 11)),
name: pdbLine.substring(12, 16).trim(),
altLoc: pdbLine.substring(16, 17).trim(),
resName: pdbLine.substring(17, 20).trim(),
chainID: pdbLine.substring(21, 22).trim(),
resSeq: parseInt(pdbLine.substring(22, 26)),
iCode: pdbLine.substring(26, 27).trim(),
x: parseFloat(pdbLine.substring(30, 38)),
y: parseFloat(pdbLine.substring(38, 46)),
z: parseFloat(pdbLine.substring(46, 54)),
occupancy: parseFloat(pdbLine.substring(54, 60)),
tempFactor: parseFloat(pdbLine.substring(60, 66)),
element: pdbLine.substring(76, 78).trim(),
charge: pdbLine.substring(78, 80).trim(),
});
} else if (pdbLine.substr(0, 6) === RESIDUE_NAME) {
// http://www.wwpdb.org/documentation/file-format-content/format33/sect3.html#SEQRES
const seqResEntry = {
serNum: parseInt(pdbLine.substring(7, 10)),
chainID: pdbLine.substring(11, 12).trim(),
numRes: parseInt(pdbLine.substring(13, 17)),
resNames: pdbLine.substring(19, 70).trim().split(' '),
};
seqRes.push(seqResEntry);
residues = residues.concat(seqResEntry.resNames.map(resName => ({
id: residues.length,
serNum: seqResEntry.serNum,
chainID: seqResEntry.chainID,
resName,
})));
if (!chains.get(seqResEntry.chainID)) {
chains.set(seqResEntry.chainID, {
id: chains.size,
chainID: seqResEntry.chainID,
// No need to save numRes, can just do chain.residues.length
});
}
}
});
// Add residues to chains
chains.forEach((chain) => {
chain.residues = residues.filter((residue) =>
residue.chainID === chain.chainID,
);
});
// Add atoms to residues
residues.forEach((residue) => {
residue.atoms = atoms.filter((atom) =>
atom.chainID === residue.chainID && atom.resSeq === residue.serNum,
);
});
return {
// Raw data from pdb
atoms,
seqRes,
// Derived
residues, // Array of residue objects
chains, // Map of chain objects keyed on chainID
};
}