Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

openchemlib-utils

Package Overview
Dependencies
Maintainers
4
Versions
94
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

openchemlib-utils - npm Package Compare versions

Comparing version 0.6.0 to 0.6.1

7

CHANGELOG.md
# Changelog
### [0.6.1](https://www.github.com/cheminfo/openchemlib-utils/compare/v0.6.0...v0.6.1) (2021-01-17)
### Bug Fixes
* correctly export combineSmiles ([a8354c3](https://www.github.com/cheminfo/openchemlib-utils/commit/a8354c37df48ef3648ca36d1c500c954d067dd60))
## [0.6.0](https://www.github.com/cheminfo/openchemlib-utils/compare/v0.5.3...v0.6.0) (2021-01-17)

@@ -4,0 +11,0 @@

@@ -431,3 +431,171 @@ 'use strict';

const MAX_R = 10;
/**
* Generate molecules and calcule predicted properties form a list of smiles and fragments
* @param {string} [coreSmiles]
* @param {array} [fragments] Array of {smiles,R1,R2,...}
* @param {object} [options={}]
* @param {function} [options.onStep] method to execute each new molecules
* @param {boolean} [options.complexity] returns only the number of molecules to evaluate
* @return {Promise} promise that resolves to molecules or complexity as a number
*/
async function combineSmiles(coreSmiles, fragments, options = {}) {
const { complexity = false } = options;
const core = getCore(coreSmiles);
const rGroups = getRGroups(core, fragments);
if (complexity) {
return getComplexity(rGroups);
}
return generate(core, rGroups, options);
}
function getComplexity(rGroups) {
let complexity = 1;
for (let rGroup of rGroups) {
complexity *= rGroup.smiles.length;
}
return complexity;
}
async function generate(core, rGroups, options = {}) {
const { onStep } = options;
const molecules = {};
const sizes = new Array(rGroups.length);
const currents = new Array(rGroups.length);
for (let i = 0; i < rGroups.length; i++) {
sizes[i] = rGroups[i].smiles.length - 1;
currents[i] = 0;
}
let position = 0;
let counter = 0;
while (true) {
counter++;
while (position < currents.length) {
if (currents[position] < sizes[position]) {
if (onStep) {
await onStep(counter);
}
appendMolecule(molecules, core, rGroups, currents);
currents[position]++;
for (let i = 0; i < position; i++) {
currents[i] = 0;
}
position = 0;
} else {
position++;
}
}
if ((position = currents.length)) {
if (onStep) {
await onStep(counter);
}
appendMolecule(molecules, core, rGroups, currents);
break;
}
}
return Object.keys(molecules)
.map((key) => molecules[key])
.sort((m1, m2) => m1.mw - m2.mw);
}
function appendMolecule(molecules, core, rGroups, currents) {
let newSmiles = core.smiles;
for (let i = 0; i < currents.length; i++) {
newSmiles += `.${rGroups[i].smiles[currents[i]]}`;
}
const OCL = getOCL();
const currentMol = OCL.Molecule.fromSmiles(newSmiles);
const idCode = currentMol.getIDCode();
if (!molecules[idCode]) {
let molecule = {};
molecules[idCode] = molecule;
molecule.smiles = currentMol.toSmiles();
molecule.combinedSmiles = newSmiles;
molecule.idCode = idCode;
molecule.molfile = currentMol.toMolfile();
const props = new OCL.MoleculeProperties(currentMol);
molecule.nbHAcceptor = props.acceptorCount;
molecule.nbHDonor = props.donorCount;
molecule.logP = props.logP;
molecule.logS = props.logS;
molecule.PSA = props.polarSurfaceArea;
molecule.nbRottable = props.rotatableBondCount;
molecule.nbStereoCenter = props.stereoCenterCount;
let mf = currentMol.getMolecularFormula();
molecule.mf = mf.formula;
molecule.mw = mf.relativeWeight;
}
}
function getCore(coreSmiles) {
let core = {
originalSmiles: coreSmiles,
smiles: coreSmiles.replace(/\[R([1-4])\]/g, '%5$1'),
};
for (let i = 0; i < MAX_R; i++) {
if (core.originalSmiles.indexOf(`[R${i}]`) > -1) core[`R${i}`] = true;
}
return core;
}
function getRGroups(core, fragments) {
let rGroups = {};
for (const fragment of fragments) {
if (fragment.smiles) {
const smiles = updateRPosition(fragment.smiles);
for (let i = 0; i < MAX_R; i++) {
if (core[`R${i}`]) {
// we only consider the R that are in the core
if (fragment[`R${i}`]) {
if (!rGroups[`R${i}`]) {
rGroups[`R${i}`] = {
group: `R${i}`,
smiles: [],
};
}
rGroups[`R${i}`].smiles.push(smiles.replace(/\[R\]/, `(%5${i})`));
}
}
}
}
}
return Object.keys(rGroups).map((key) => rGroups[key]);
}
function updateRPosition(smiles) {
// R group should not be at the beginning
if (smiles.indexOf('[R]') !== 0) return smiles;
if (smiles.length === 3) return '[H][R]';
// we are in trouble ... we need to move the R
let newSmiles = smiles.replace('[R]', '');
// we need to check where we should put the R group
let level = 0;
for (let j = 0; j < newSmiles.length; j++) {
let currentChar = newSmiles.charAt(j);
let currentSubstring = newSmiles.substr(j);
if (currentChar === '(') {
level++;
} else if (currentChar === ')') {
level--;
} else if (level === 0) {
if (currentSubstring.match(/^[a-z]/)) {
return `${newSmiles.substr(0, j + 1)}([R])${newSmiles.substr(j + 1)}`;
} else if (currentSubstring.match(/^[A-Z][a-z]/)) {
return `${newSmiles.substr(0, j + 2)}([R])${newSmiles.substr(j + 2)}`;
} else if (currentSubstring.match(/^[A-Z]/)) {
return `${newSmiles.substr(0, j + 1)}([R])${newSmiles.substr(j + 1)}`;
}
}
}
return smiles;
}
/**
* Returns various information about atoms in the molecule

@@ -917,2 +1085,3 @@ * @param {OCL.Molecule} [molecule]

exports.addDiastereotopicMissingChirality = addDiastereotopicMissingChirality;
exports.combineSmiles = combineSmiles;
exports.getAtomsInfo = getAtomsInfo;

@@ -919,0 +1088,0 @@ exports.getConnectivityMatrix = getConnectivityMatrix;

2

package.json
{
"name": "openchemlib-utils",
"version": "0.6.0",
"version": "0.6.1",
"description": "",

@@ -5,0 +5,0 @@ "main": "lib/index.js",

@@ -11,2 +11,3 @@ export * from './diastereotopic/addDiastereotopicMissingChirality';

export * from './util/combineSmiles';
export * from './util/getAtomsInfo';

@@ -13,0 +14,0 @@ export * from './util/getConnectivityMatrix';

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc