New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

mass-fragmentation

Package Overview
Dependencies
Maintainers
1
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mass-fragmentation - npm Package Compare versions

Comparing version

to
0.5.0

src/database/getDatabase.js

163

lib/index.js

@@ -7,8 +7,3 @@ 'use strict';

var openchemlibUtils = require('openchemlib-utils');
var OCL = require('openchemlib');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var OCL__default = /*#__PURE__*/_interopDefaultLegacy(OCL);
/**

@@ -663,78 +658,43 @@ * The function performs the fragmentation of all single linear bonds

function applyFragmentationReactions(
ionizedFragments,
reactions,
maxDepth,
) {
const fragmentationReactions = reactions.filter(
(reaction) => reaction.Label !== 'Ionization',
);
for (let ionizedMolecule of ionizedFragments.products) {
if (ionizedMolecule.children?.length > 0) {
for (let child of ionizedMolecule.children) {
applyFragmentationReactions(child, fragmentationReactions, maxDepth);
}
} else {
let moleculeToFragment = OCL__default["default"].Molecule.fromIDCode(ionizedMolecule.idCode);
let fragmentation = openchemlibUtils.applyReactions(
[moleculeToFragment],
fragmentationReactions,
{
maxDepth,
},
);
ionizedMolecule.children = fragmentation;
}
function getDatabase(databaseName) {
if (databaseName === 'cid') {
return cid;
}
}
function applyIonizationReactions(molecule, reactions, ionizationLevel) {
const ionizationReaction = reactions.filter(
(reaction) => reaction.Label === 'Ionization',
);
let ionization = openchemlibUtils.applyReactions([molecule], ionizationReaction, {
maxDepth: 1,
});
function ionize(reactant, ionizationReactions, currentIonizationLevel) {
for (let product of reactant.products) {
if (currentIonizationLevel < ionizationLevel) {
let currentMolecule = OCL__default["default"].Molecule.fromIDCode(product.idCode);
let ionizedFragments = openchemlibUtils.applyReactions(
[currentMolecule],
ionizationReactions,
{
maxDepth: 1,
},
);
product.children = ionizedFragments;
currentIonizationLevel = currentIonizationLevel + 1;
if (product.children.length > 0) {
for (let child of product.children) {
ionize(child, ionizationReactions, currentIonizationLevel);
}
}
}
}
/**
* @description Recursively insert monoisotopic mass information into the fragmentation trees, products and get array of monoisotopic masses
* @param {Array} trees Fragmentation trees
* @param {Array} products Fragmentation trees grouped by product idCode
* @returns {object} Object with the following properties:
* - masses: array of monoisotopic masses
* - trees: array of fragmentation trees with monoisotopic mass
* - products: array of trees grouped by product idCode with monoisotopic mass
*/
function insertMfInfoFragments(trees, products) {
let masses = {};
for (let tree of trees) {
mfInfoFragments(tree, masses);
}
for (let ionizedFragment of ionization) {
ionize(ionizedFragment, ionizationReaction, 1);
for (let product of products) {
const productMF = new mfParser.MF(product.mf);
product.monoisotopicMass =
Math.round(
(productMF.getInfo().observedMonoisotopicMass ??
productMF.getInfo().monoisotopicMass) * 10000,
) / 10000;
}
return ionization;
}
const masses = {};
function insertMfInfoFragments(fragmentation) {
for (let fragment of fragmentation) {
mfInfoFragments(fragment);
}
return {
masses: Object.keys(masses).map(Number),
tree: fragmentation,
trees,
products,
};
}
function mfInfoFragments(reaction) {
/**
* @description Recursively insert monoisotopic mass information into the fragmentation trees and get array of monoisotopic masses
* @param {*} reaction Fragmentation trees
* @param {*} masses Object with monoisotopic masses
*/
function mfInfoFragments(reaction, masses) {
if (reaction?.reactant) {

@@ -752,7 +712,2 @@ const reactantMF = new mfParser.MF(reaction.reactant.mf);

for (const product of reaction.products) {
if (product.children?.length > 0) {
for (const child of product.children) {
mfInfoFragments(child);
}
}
const productMF = new mfParser.MF(product.mf);

@@ -765,2 +720,7 @@ product.monoisotopicMass =

masses[product.monoisotopicMass] = true;
if (product.children?.length > 0) {
for (const child of product.children) {
mfInfoFragments(child, masses);
}
}
}

@@ -770,31 +730,34 @@ }

const databases = {
cid,
};
//ionizationLevel fix the maximum depth of the ionization reactions in the molecule
/**
* @description Fragment a molecule by applying reactions from a custom database of reactions
* @param {import('openchemlib').Molecule} molecule - The OCL molecule to be fragmented
* @param {Object} [options={}]
* @param {string} [options.databaseName='cid'] - The database to be used
* @param {string} [options.mode='positive'] - The mode to be used
* @param {number} [options.maxDepth=5] - The maximum depth of the fragmentation tree
* @returns {object} In-Silico fragmentation results with the following properties:
* - masses: array of monoisotopic masses
* - trees: array of fragmentation trees
* - products: array of trees grouped by product idCode
*/
function reactionFragmentation(molecule, options = {}) {
let {
database = 'cid',
mode = 'positive',
maxDepth = 0,
ionizationLevel = 1,
} = options;
if (maxDepth === 0) {
let mass = molecule.getMolecularFormula().absoluteWeight;
maxDepth = Math.round(mass / 10);
let { databaseName = 'cid', mode = 'positive', maxDepth = 5 } = options;
let database = getDatabase(databaseName);
if (!database) {
throw new Error(`Database ${databaseName} not found`);
}
const reactions = databases[database][mode];
let ionizedFragments = applyIonizationReactions(
molecule,
reactions,
ionizationLevel,
const reactions = database[mode];
let fragments = openchemlibUtils.applyReactions([molecule], reactions, {
maxDepth,
});
let { masses, trees, products } = insertMfInfoFragments(
fragments.trees,
fragments.products,
);
for (let ionizedFragment of ionizedFragments) {
applyFragmentationReactions(ionizedFragment, reactions, maxDepth);
}
let { masses, tree } = insertMfInfoFragments(ionizedFragments);
return {
masses,
tree,
trees,
products,
};

@@ -801,0 +764,0 @@ }

{
"name": "mass-fragmentation",
"version": "0.4.0",
"version": "0.5.0",
"description": "Code to fragment molecules",

@@ -24,8 +24,9 @@ "main": "lib/index.js",

"mf-parser": "^2.3.0",
"openchemlib-utils": "^2.4.0"
"openchemlib-utils": "^2.7.0"
},
"devDependencies": {
"openchemlib": "^8.2.0"
"openchemlib": "^8.3.0",
"react-tree-svg": "^0.1.0"
},
"gitHead": "bc42b1937c4d78b61bf0548c5bf1397ab52d645a"
"gitHead": "c697f5fab6e34146c16194f54cead9ddd1c8465f"
}

@@ -13,5 +13,19 @@ import OCL from 'openchemlib';

};
const result = reactionFragmentation(molecule, options);
const { masses, trees, products } = reactionFragmentation(
molecule,
options,
);
expect(result).toMatchSnapshot();
expect(Object.keys(products[0])).toMatchInlineSnapshot(`
[
"idCode",
"mf",
"trees",
"reactions",
"minSteps",
"monoisotopicMass",
]
`);
expect(masses).toHaveLength(17);
expect(trees).toMatchSnapshot();
});

@@ -23,17 +37,155 @@ it('tropylium rearrangement: MDMA after Alpha cleavage', async () => {

};
const result = reactionFragmentation(molecule, options);
expect(result).toMatchSnapshot();
const { masses, trees, products } = reactionFragmentation(
molecule,
options,
);
expect(Object.keys(products[0])).toMatchInlineSnapshot(`
[
"idCode",
"mf",
"trees",
"reactions",
"minSteps",
"monoisotopicMass",
]
`);
expect(masses).toHaveLength(7);
expect(trees).toMatchSnapshot();
});
it('Full fragmentation: MDMA', async () => {
const molecule = Molecule.fromSmiles('CNC(Cc1ccc2c(c1)OCO2)C');
const molecule = Molecule.fromSmiles('CC(CC1=CC2=C(C=C1)OCO2)NC');
const options = {
ionizationLevel: 1,
maxDepth: 5,
};
let { masses, trees, products } = reactionFragmentation(molecule, options);
expect(masses).toMatchInlineSnapshot(`
[
193.1103,
194.1176,
31.0422,
32.0495,
163.0754,
135.0441,
68.0257,
45.6862,
30.047,
28.0313,
82.0413,
55.03,
97.5624,
65.3774,
65.0414,
68.5296,
97.0585,
58.0651,
136.0519,
193.1097,
135.0446,
]
`);
expect(products[0]).toMatchInlineSnapshot(`
{
"idCode": "dg~DBMBmeJYW]gJxZB@jj@@",
"mf": "C11H16NO2(+)",
"minSteps": 1,
"monoisotopicMass": 194.1176,
"reactions": [
"eM\`BN\`~b@!eM\`\`fN\`~c@#Q[ Q[#!R@AM?DquRo@ !R@AM?Dqtzo@",
],
"trees": [
{
"products": [
{
"children": [],
"flag": true,
"idCode": "dg~DBMBmeJYW]gJxZB@jj@@",
"mf": "C11H16NO2(+)",
"molfile": "
Actelion Java MolfileCreator 1.0
const result = reactionFragmentation(molecule, options);
14 15 0 0 0 0 0 0 0 0999 V2000
18.7073 -7.2671 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
19.5677 -7.7768 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
19.5565 -8.7767 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
18.6849 -9.2670 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
18.6737 -10.2669 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
17.8021 -10.7572 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
16.9417 -10.2475 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
16.9529 -9.2475 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
17.8245 -8.7573 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
16.1911 -10.9082 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
16.5876 -11.8263 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
17.5832 -11.7329 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
20.4444 -7.2836 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
21.3075 -7.7768 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0 0 0 0
2 3 1 0 0 0 0
3 4 1 0 0 0 0
4 5 2 0 0 0 0
5 6 1 0 0 0 0
6 7 2 0 0 0 0
7 8 1 0 0 0 0
8 9 2 0 0 0 0
4 9 1 0 0 0 0
7 10 1 0 0 0 0
10 11 1 0 0 0 0
11 12 1 0 0 0 0
6 12 1 0 0 0 0
13 2 1 0 0 0 0
13 14 1 0 0 0 0
M CHG 1 13 1
M END
",
},
],
"reactant": {
"idCode": "dg~D@MBdie]v\\\\kahHBjh@@",
"mf": "C11H15NO2",
"molfile": "
Actelion Java MolfileCreator 1.0
expect(result).toMatchSnapshot();
14 15 0 0 0 0 0 0 0 0999 V2000
1.7321 -1.5000 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1.7321 -0.5000 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
2.5981 -0.0000 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
3.4641 -0.5000 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
4.3301 -0.0000 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
5.1962 -0.5000 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
5.1962 -1.5000 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
4.3301 -2.0000 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
3.4641 -1.5000 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
6.1472 -1.8090 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
6.7350 -1.0000 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
6.1472 -0.1910 -0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0
0.8660 -0.0000 -0.0000 N 0 0 0 0 0 0 0 0 0 0 0 0
0.0000 -0.5000 -0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0
1 2 1 0 0 0 0
2 3 1 0 0 0 0
3 4 1 0 0 0 0
4 5 2 0 0 0 0
5 6 1 0 0 0 0
6 7 2 0 0 0 0
7 8 1 0 0 0 0
8 9 2 0 0 0 0
4 9 1 0 0 0 0
7 10 1 0 0 0 0
10 11 1 0 0 0 0
11 12 1 0 0 0 0
6 12 1 0 0 0 0
2 13 1 0 0 0 0
13 14 1 0 0 0 0
M END
",
},
"reaction": {
"Label": "Ionization",
"rxnCode": "eM\`BN\`~b@!eM\`\`fN\`~c@#Q[ Q[#!R@AM?DquRo@ !R@AM?Dqtzo@",
},
},
],
}
`);
expect(trees).toMatchSnapshot();
});
});

@@ -1,36 +0,39 @@

import { cid } from './database/collisionInducedDissociation';
import { applyFragmentationReactions } from './utils/applyFragmentationReactions';
import { applyIonizationReactions } from './utils/applyIonizationReactions';
import { applyReactions } from 'openchemlib-utils';
import getDatabase from './database/getDatabase';
import { insertMfInfoFragments } from './utils/insertMfInfoFragments';
const databases = {
cid,
};
//ionizationLevel fix the maximum depth of the ionization reactions in the molecule
/**
* @description Fragment a molecule by applying reactions from a custom database of reactions
* @param {import('openchemlib').Molecule} molecule - The OCL molecule to be fragmented
* @param {Object} [options={}]
* @param {string} [options.databaseName='cid'] - The database to be used
* @param {string} [options.mode='positive'] - The mode to be used
* @param {number} [options.maxDepth=5] - The maximum depth of the fragmentation tree
* @returns {object} In-Silico fragmentation results with the following properties:
* - masses: array of monoisotopic masses
* - trees: array of fragmentation trees
* - products: array of trees grouped by product idCode
*/
export function reactionFragmentation(molecule, options = {}) {
let {
database = 'cid',
mode = 'positive',
maxDepth = 0,
ionizationLevel = 1,
} = options;
if (maxDepth === 0) {
let mass = molecule.getMolecularFormula().absoluteWeight;
maxDepth = Math.round(mass / 10);
let { databaseName = 'cid', mode = 'positive', maxDepth = 5 } = options;
let database = getDatabase(databaseName);
if (!database) {
throw new Error(`Database ${databaseName} not found`);
}
const reactions = databases[database][mode];
let ionizedFragments = applyIonizationReactions(
molecule,
reactions,
ionizationLevel,
const reactions = database[mode];
let fragments = applyReactions([molecule], reactions, {
maxDepth,
});
let { masses, trees, products } = insertMfInfoFragments(
fragments.trees,
fragments.products,
);
for (let ionizedFragment of ionizedFragments) {
applyFragmentationReactions(ionizedFragment, reactions, maxDepth);
}
let { masses, tree } = insertMfInfoFragments(ionizedFragments);
return {
masses,
tree,
trees,
products,
};
}
import { MF } from 'mf-parser';
const masses = {};
export function insertMfInfoFragments(fragmentation) {
for (let fragment of fragmentation) {
mfInfoFragments(fragment);
/**
* @description Recursively insert monoisotopic mass information into the fragmentation trees, products and get array of monoisotopic masses
* @param {Array} trees Fragmentation trees
* @param {Array} products Fragmentation trees grouped by product idCode
* @returns {object} Object with the following properties:
* - masses: array of monoisotopic masses
* - trees: array of fragmentation trees with monoisotopic mass
* - products: array of trees grouped by product idCode with monoisotopic mass
*/
export function insertMfInfoFragments(trees, products) {
let masses = {};
for (let tree of trees) {
mfInfoFragments(tree, masses);
}
for (let product of products) {
const productMF = new MF(product.mf);
product.monoisotopicMass =
Math.round(
(productMF.getInfo().observedMonoisotopicMass ??
productMF.getInfo().monoisotopicMass) * 10000,
) / 10000;
}
return {
masses: Object.keys(masses).map(Number),
tree: fragmentation,
trees,
products,
};
}
function mfInfoFragments(reaction) {
/**
* @description Recursively insert monoisotopic mass information into the fragmentation trees and get array of monoisotopic masses
* @param {*} reaction Fragmentation trees
* @param {*} masses Object with monoisotopic masses
*/
function mfInfoFragments(reaction, masses) {
if (reaction?.reactant) {

@@ -28,7 +50,2 @@ const reactantMF = new MF(reaction.reactant.mf);

for (const product of reaction.products) {
if (product.children?.length > 0) {
for (const child of product.children) {
mfInfoFragments(child);
}
}
const productMF = new MF(product.mf);

@@ -41,4 +58,9 @@ product.monoisotopicMass =

masses[product.monoisotopicMass] = true;
if (product.children?.length > 0) {
for (const child of product.children) {
mfInfoFragments(child, masses);
}
}
}
}
}

Sorry, the diff of this file is not supported yet