UNPKG

@jenskrumsieck/moleculesjs

Version:
118 lines (117 loc) 5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const atom_1 = require("./primitives/atom"); const molecule_1 = __importDefault(require("./primitives/molecule")); const vector3_1 = require("./primitives/vector3"); class CIF { content; a; b; c; alpha; beta; gamma; constructor(content) { this.content = content.replace(/(?:[\r])/g, ""); this.setParameters(); } static parse(content) { var cif = new CIF(content); return cif.parse(); } parse() { var loops = this.content.split('loop_'); var molLoop = loops.find(s => s.includes('_atom_site_label')); var bondLoop = loops.find(s => s.includes('_geom_bond_atom_site_label_1')); var atoms = this.extractAtoms(molLoop); var bonds = this.extractBonds(bondLoop, atoms); return new molecule_1.default({ atoms, bonds }); } extractAtoms(molLoop) { let lines = molLoop.split('\n'); let headers = lines.filter(s => s.trim().startsWith('_')); let body = lines.filter(s => !s.trim().startsWith('_')); let disorderIndex = headers.indexOf('_atom_site_disorder_group'); let data = []; for (var i = 0; i < body.length; i++) { var raw_data = body[i].split(' '); if (disorderIndex >= 0 && disorderIndex < raw_data.length && raw_data[disorderIndex] == "2" || raw_data.length != headers.length) continue; data.push(raw_data); } return this.calculateCartesian(data); } extractBonds(bondLoop, atoms) { let lines = bondLoop.split('\n'); let body = lines.filter(s => !s.trim().startsWith('_')); var bonds = []; for (var i = 0; i < body.length; i++) { var raw_data = body[i].split(" "); let atom1 = raw_data[0]; let atom2 = raw_data[1]; //check if atoms existing if (atoms.find(s => s.title == atom1) && atoms.find(s => s.title == atom2)) bonds.push({ atom1: atoms.find(s => s.title == atom1), atom2: atoms.find(s => s.title == atom2) }); } return bonds; } cellParameters(type) { let parameters = []; let lines = this.content.split('\n'); for (var i = 0; i < lines.length; i++) { if (lines[i].startsWith("_" + type)) { //parameter value contains uncertainity in brackets, so strip that var tmp = lines[i].split(" "); var value = tmp[tmp.length - 1]; //last item parameters.push(value.split('(')[0]); } } return parameters; } setParameters() { var lengths = this.cellParameters('cell_length'); var angles = this.cellParameters('cell_angle'); this.a = parseFloat(lengths[0]); this.b = parseFloat(lengths[1]); this.c = parseFloat(lengths[2]); this.alpha = parseFloat(angles[0]); this.beta = parseFloat(angles[1]); this.gamma = parseFloat(angles[2]); } calculateCartesian(data) { //variables introduced to deconfuse var atoms = []; for (var i = 0; i < data.length; i++) { //get xyz in fractional coordinates //1 is label, 2 is x, 3 is y, 4 is z let xFrac = data[i][2].split('(')[0]; let yFrac = data[i][3].split('(')[0]; let zFrac = data[i][4].split('(')[0]; let angle = Math.PI / 180; //transformation matrix: see https://en.wikipedia.org/wiki/Fractional_coordinates#Conversion_to_Cartesian_coordinates //a21, a31, a32 = 0 //a11 = a //other matrix entries as below: let a12 = this.b * Math.cos(this.gamma * angle); let a13 = this.c * Math.cos(this.beta * angle); let a22 = this.b * Math.sin(this.gamma * angle); let a23 = this.c * (Math.cos(this.alpha * angle) - Math.cos(this.beta * angle) * Math.cos(this.gamma * angle)) / Math.sin(this.gamma * angle); let a33 = this.c * (Math.sqrt(1 - Math.pow(Math.cos(this.alpha * angle), 2) - Math.pow(Math.cos(this.beta * angle), 2) - Math.pow(Math.cos(this.gamma * angle), 2) + 2 * Math.cos(this.alpha * angle) * Math.cos(this.beta * angle) * Math.cos(this.gamma * angle))) / Math.sin(this.gamma * angle); //xyz = [A]*(xyz)_frac let x = this.a * xFrac + a12 * yFrac + a13 * zFrac; let y = a22 * yFrac + a23 * zFrac; let z = a33 * zFrac; let element = data[i][1]; var atom = new atom_1.Atom(element, new vector3_1.Vector3(x, y, z)); atom.title = data[i][0]; atoms.push(atom); } return atoms; } } exports.default = CIF;