smiles-drawer
Version:
A SMILES drawer and parser. Generate molecular structure depictions in pure JavaScript.
176 lines (155 loc) • 6.37 kB
JavaScript
// @ts-check
import Ring from './Ring';
import Vertex from './Vertex';
/**
* A class representing a ring connection.
*
* @property {Number} id The id of this ring connection.
* @property {Number} firstRingId A ring id.
* @property {Number} secondRingId A ring id.
* @property {Set<Number>} vertices A set containing the vertex ids participating in the ring connection.
*/
export default class RingConnection {
/**
* The constructor for the class RingConnection.
*
* @param {Ring} firstRing A ring.
* @param {Ring} secondRing A ring.
*/
constructor(firstRing, secondRing) {
this.id = null;
this.firstRingId = firstRing.id;
this.secondRingId = secondRing.id;
this.vertices = new Set();
for (let m = 0; m < firstRing.members.length; m++) {
let c = firstRing.members[m];
for (let n = 0; n < secondRing.members.length; n++) {
let d = secondRing.members[n];
if (c === d) {
this.addVertex(c);
}
}
}
}
/**
* Adding a vertex to the ring connection.
*
* @param {Number} vertexId A vertex id.
*/
addVertex(vertexId) {
this.vertices.add(vertexId);
}
/**
* Update the ring id of this ring connection that is not the ring id supplied as the second argument.
*
* @param {Number} ringId A ring id. The new ring id to be set.
* @param {Number} otherRingId A ring id. The id that is NOT to be updated.
*/
updateOther(ringId, otherRingId) {
if (this.firstRingId === otherRingId) {
this.secondRingId = ringId;
}
else {
this.firstRingId = ringId;
}
}
/**
* Returns a boolean indicating whether or not a ring with a given id is participating in this ring connection.
*
* @param {Number} ringId A ring id.
* @returns {Boolean} A boolean indicating whether or not a ring with a given id participates in this ring connection.
*/
containsRing(ringId) {
return this.firstRingId === ringId || this.secondRingId === ringId;
}
/**
* Checks whether or not this ring connection is a bridge in a bridged ring.
*
* @param {Vertex[]} vertices The array of vertices associated with the current molecule.
* @returns {Boolean} A boolean indicating whether or not this ring connection is a bridge.
*/
isBridge(vertices) {
if (this.vertices.size > 2) {
return true;
}
// For 2 shared atoms, check if they form a triangle with a common
// neighbor that's in one of the two rings. This detects bridged
// bicyclic systems (e.g. norbornane, oxanorbornane) where SSSR
// produces a small ring and a large ring sharing 2 bridgehead atoms.
if (this.vertices.size === 2) {
let [v1, v2] = [...this.vertices];
let v2NeighbourSet = new Set(vertices[v2].neighbours);
for (let n of vertices[v1].neighbours) {
if (n !== v2 && v2NeighbourSet.has(n)) {
let nRings = vertices[n].value.rings;
if (nRings.includes(this.firstRingId) || nRings.includes(this.secondRingId)) {
return true;
}
}
}
}
return false;
}
/**
* Checks whether or not two rings are connected by a bridged bond.
*
* @static
* @param {RingConnection[]} ringConnections An array of ring connections containing the ring connections associated with the current molecule.
* @param {Vertex[]} vertices An array of vertices containing the vertices associated with the current molecule.
* @param {Number} firstRingId A ring id.
* @param {Number} secondRingId A ring id.
* @returns {Boolean} A boolean indicating whether or not two rings ar connected by a bridged bond.
*/
static isBridge(ringConnections, vertices, firstRingId, secondRingId) {
let ringConnection = null;
for (let i = 0; i < ringConnections.length; i++) {
ringConnection = ringConnections[i];
if ((ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId)
|| (ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId)
) {
return ringConnection.isBridge(vertices);
}
}
return false;
}
/**
* Retruns the neighbouring rings of a given ring.
*
* @static
* @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.
* @param {Number} ringId A ring id.
* @returns {Number[]} An array of ring ids of neighbouring rings.
*/
static getNeighbours(ringConnections, ringId) {
let neighbours = [];
for (let i = 0; i < ringConnections.length; i++) {
let ringConnection = ringConnections[i];
if (ringConnection.firstRingId === ringId) {
neighbours.push(ringConnection.secondRingId);
}
else if (ringConnection.secondRingId === ringId) {
neighbours.push(ringConnection.firstRingId);
}
}
return neighbours;
}
/**
* Returns an array of vertex ids associated with a given ring connection.
*
* @static
* @param {RingConnection[]} ringConnections An array of ring connections containing ring connections associated with the current molecule.
* @param {Number} firstRingId A ring id.
* @param {Number} secondRingId A ring id.
* @returns {Number[]} An array of vertex ids associated with the ring connection.
*/
static getVertices(ringConnections, firstRingId, secondRingId) {
for (let i = 0; i < ringConnections.length; i++) {
let ringConnection = ringConnections[i];
if ((ringConnection.firstRingId === firstRingId && ringConnection.secondRingId === secondRingId)
|| (ringConnection.firstRingId === secondRingId && ringConnection.secondRingId === firstRingId)
) {
return [...ringConnection.vertices];
}
}
}
}