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

mf-parser

Package Overview
Dependencies
Maintainers
6
Versions
73
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mf-parser - npm Package Compare versions

Comparing version 0.1.0 to 0.4.2

src/util/getInfo.js

34

package.json
{
"name": "mf-parser",
"version": "0.1.0",
"description": "Parse molecular formula",
"main": "./src/index.js",
"version": "0.4.2",
"description": "",
"main": "src/index.js",
"files": [
"src"
],
"scripts": {
"eslint": "eslint src test",
"eslint-fix": "npm run eslint -- --fix",
"test": "run-s testonly eslint",
"test-travis": "eslint src && jest --coverage && codecov",
"testonly": "jest",
"build": "cheminfo build --no-source-map"
},
"repository": {
"type": "git",
"url": "https://github.com/cheminfo-js/mf-parser.git"
"url": "git+https://github.com/cheminfo-js/mf-parser.git"
},
"keywords": [],
"author": "Luc Patiny <luc@patiny.com>",
"author": "Luc Patiny",
"license": "MIT",

@@ -27,15 +19,7 @@ "bugs": {

},
"homepage": "https://github.com/cheminfo-js/mf-parser#readme",
"jest": {
"testEnvironment": "node"
},
"devDependencies": {
"cheminfo-tools": "^1.20.1",
"codecov": "^3.0.0",
"eslint": "^4.12.0",
"eslint-config-cheminfo": "^1.8.0",
"eslint-plugin-no-only-tests": "^2.0.0",
"jest": "^21.2.1",
"npm-run-all": "^4.1.2"
"homepage": "https://github.com/cheminfo-js/mf-parser/tree/master/packages/mf-parser#readme",
"dependencies": {
"atom-sorter": "^0.4.2",
"molecular-formula-generator": "^0.0.0"
}
}
# mf-parser
[![NPM version][npm-image]][npm-url]
[![build status][travis-image]][travis-url]
[![Test coverage][codecov-image]][codecov-url]
[![David deps][david-image]][david-url]
[![npm download][download-image]][download-url]
Parse molecular formula
.
## Installation
`$ npm install mf-parser`
`$ npm install --save mf-parser`
## [API Documentation](https://cheminfo-js.github.io/mf-parser/)
## Usage
## Example
```js
const parseToHtml = require('mf-parser').parseToHtml;
let html = parseToHtml('Et3N . 2HCl);
```
import library from 'mf-parser';
You may also be interested to parse first the MF and then retrieve display representation
```js
const MFParser = require('mf-parser');
let parsed = MFParser.parse('Et3N . 2HCl');
let displayed = MFParser.toDisplay(parsed);
// displayed could be used to ocreate a custom renderer
console.log(displayed);
const result = library(args);
// result is ...
```
## License
[MIT](./LICENSE)
[MIT](./LICENSE)
[npm-image]: https://img.shields.io/npm/v/mf-parser.svg?style=flat-square
[npm-url]: https://www.npmjs.com/package/mf-parser
[travis-image]: https://img.shields.io/travis/cheminfo-js/mf-parser/master.svg?style=flat-square
[travis-url]: https://travis-ci.org/cheminfo-js/mf-parser
[codecov-image]: https://img.shields.io/codecov/c/github/cheminfo-js/mf-parser.svg?style=flat-square
[codecov-url]: https://codecov.io/gh/cheminfo-js/mf-parser
[david-image]: https://img.shields.io/david/cheminfo-js/mf-parser.svg?style=flat-square
[david-url]: https://david-dm.org/cheminfo-js/mf-parser
[download-image]: https://img.shields.io/npm/dm/mf-parser.svg?style=flat-square
[download-url]: https://www.npmjs.com/package/mf-parser

@@ -5,15 +5,140 @@ 'use strict';

test('MF', () => {
test('MF of Et3N.HCl', () => {
var mf = new MF('Et3N.HCl');
var parts = mf.toParts();
expect(parts).toEqual(
[[
{kind: 'atom', value: 'Et', multiplier: 3},
{kind: 'atom', value: 'C', multiplier: 6},
{kind: 'atom', value: 'H', multiplier: 15},
{kind: 'atom', value: 'N', multiplier: 1}
], [
{kind: 'atom', value: 'Cl', multiplier: 1},
{kind: 'atom', value: 'H', multiplier: 1},
{kind: 'atom', value: 'Cl', multiplier: 1}
]]
);
var newMF = mf.toMF();
expect(newMF).toBe('C6H15N.HCl');
mf.canonize();
let html = mf.toHtml();
expect(html).toBe('C<sub>6</sub>H<sub>15</sub>N<sub>1</sub> • H<sub>1</sub>Cl<sub>1</sub>');
let info = mf.getInfo();
expect(info).toEqual({parts:
[{mass: 101.19022990269394,
monoisotopicMass: 101.12044948788001,
charge: 0,
mf: 'C6H15N'},
{mass: 36.460878336663775,
monoisotopicMass: 35.97667771423,
charge: 0,
mf: 'HCl'}],
monoisotopicMass: 137.09712720211002,
mass: 137.6511082393577,
charge: 0,
mf: 'C6H15N.HCl'}
);
});
test('MF of (Me2CH)3N no expand', () => {
var mf = new MF('(Me2CH)3N');
var parts = mf.toParts({expand: false});
expect(parts).toEqual(
[[
{kind: 'atom', value: 'C', multiplier: 3},
{kind: 'atom', value: 'H', multiplier: 3},
{kind: 'atom', value: 'Me', multiplier: 6},
{kind: 'atom', value: 'N', multiplier: 1}
]]
);
var newMF = mf.toMF();
expect(newMF).toBe('C3H3Me6N');
let info = mf.getInfo();
expect(info).toEqual(
{mass: 143.27008211723435,
monoisotopicMass: 143.16739968126,
charge: 0,
mf: 'C3H3Me6N'
}
);
});
test('MF of (+)SO4(+)(-2)2', () => {
var mf = new MF('(+)SO4(+)(-2)2');
var parts = mf.toParts();
expect(parts).toEqual(
[[
{kind: 'atom', value: 'O', multiplier: 4},
{kind: 'atom', value: 'S', multiplier: 1},
{kind: 'charge', value: -2},
]]
);
var newMF = mf.toMF();
expect(newMF).toBe('O4S(-2)');
let info = mf.getInfo();
expect(info).toEqual({
monoisotopicMass: 95.95172965268,
mass: 96.06240710340018,
charge: -2,
observedMonoisotopicMass: 47.97641340624907,
mf: 'O4S(-2)'}
);
});
test('MF of NC[13C][15N]2NN2', () => {
var mf = new MF('NC[13C][15N]2NN2');
var parts = mf.toParts();
expect(parts).toEqual(
[[
{kind: 'atom', value: 'C', multiplier: 1},
{kind: 'isotope', value: {atom: 'C', isotope: 13}, multiplier: 1},
{kind: 'atom', value: 'N', multiplier: 4},
{kind: 'isotope', value: {atom: 'N', isotope: 15}, multiplier: 2}
]]
);
let info = mf.getInfo();
expect(info).toEqual({
monoisotopicMass: 111.01586865055,
mass: 111.04112137534844,
charge: 0,
mf: 'C[13C]N4[15N]2'}
);
var newMF = mf.toMF();
expect(newMF).toBe('C[13C]N4[15N]2');
});
test('MF of CC{50,50}H', () => {
var mf = new MF('HC{50,50}C');
var parts = mf.toParts();
expect(parts).toEqual(
[[
{kind: 'atom', value: 'C', multiplier: 1},
{kind: 'isotopeRatio', value: {atom: 'C', ratio: [50, 50]}, multiplier: 1},
{kind: 'atom', value: 'H', multiplier: 1}
]]
); mf.canonize(); var toHtml = mf.toHtml();
expect(toHtml).toBe('Et<sub>3</sub>N<sub>1</sub> • Cl<sub>1</sub>H<sub>1</sub>');
);
var newMF = mf.toMF();
expect(newMF).toBe('CC{50,50}H');
let info = mf.getInfo();
expect(info).toEqual({
monoisotopicMass: 25.00782503223,
mass: 25.520354068326025,
charge: 0,
mf: 'CC{50,50}H'}
);
});

@@ -20,2 +20,6 @@ 'use strict';

'C(--)': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: -2}],
'(H+)': [{kind: 'openingParenthesis', value: '('}, {kind: 'atom', value: 'H'}, {kind: 'charge', value: 1}, {kind: 'closingParenthesis', value: ')'}],
C$ABC: [{kind: 'atom', value: 'C'}, {kind: 'comment', value: 'ABC'}],
'C(-1)(-3)': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: -1}, {kind: 'charge', value: -3}],
'C(-1)2(-3)3': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: -1}, {kind: 'multiplier', value: 2}, {kind: 'charge', value: -3}, {kind: 'multiplier', value: 3}],
'C(-2)': [{kind: 'atom', value: 'C'}, {kind: 'charge', value: -2}],

@@ -29,4 +33,3 @@ 'C(H-2)': [{kind: 'atom', value: 'C'}, {kind: 'openingParenthesis', value: '('}, {kind: 'atom', value: 'H'}, {kind: 'multiplier', value: -2}, {kind: 'closingParenthesis', value: ')'}],

test('parse molecular formula', function () {
test.only('parse molecular formula', function () {
for (var key of Object.keys(tests)) {

@@ -43,2 +46,3 @@ check(key, tests[key]);

function check(mf, result) {

@@ -45,0 +49,0 @@ var parsed = parse(mf);

@@ -18,3 +18,4 @@ 'use strict';

MULTIPLIER: 'multiplier',
TEXT: 'text'
TEXT: 'text',
COMMENT: 'comment'
};

@@ -8,2 +8,4 @@ 'use strict';

const toParts = require('./util/toParts');
const getInfo = require('./util/getInfo');
const partsToMF = require('./util/partsToMF');
const partsToDisplay = require('./util/partsToDisplay');

@@ -30,5 +32,5 @@

toParts() {
toParts(options) {
if (!this.cache.parts) {
this.cache.parts = toParts(this.parsed);
this.cache.parts = toParts(this.parsed, options);
}

@@ -38,2 +40,25 @@ return this.cache.parts;

/**
* Returns an object with the global MF, global charge, monoisotopic mass and mass
* as well as the same informations for all the parts
*/
getInfo() {
if (!this.cache.info) {
this.toParts();
this.cache.info = getInfo(this.cache.parts);
}
return this.cache.info;
}
/**
* Get a canonized MF
*/
toMF() {
if (!this.cache.mf) {
this.toParts();
this.cache.mf = partsToMF(this.cache.parts);
}
return this.cache.mf;
}
canonize() {

@@ -40,0 +65,0 @@ this.toParts();

@@ -88,2 +88,5 @@ 'use strict';

this.result.push({kind: Kind.CHARGE, value: charge});
} else if (char === '$') { // it is a comment after
this.result.push({kind: Kind.COMMENT, value: this.mf.substring(this.i + 1)});
break;
} else {

@@ -96,3 +99,2 @@ this.result.push({kind: Kind.TEXT, value: char});

this.checkParenthesis();
return this.result;

@@ -191,3 +193,4 @@ }

ascii = this.mf.charCodeAt(this.i);
} while (ascii === 43 || ascii === 45 || (ascii > 47 && ascii < 58)); // closing parenthesis
} while (ascii === 43 || ascii === 45 || (ascii > 47 && ascii < 58));
this.i--;
return parseCharge(substring);

@@ -194,0 +197,0 @@ }

@@ -34,10 +34,11 @@ 'use strict';

{
mf: 'Et3N.HCl',
mf: 'Et3N.ClH',
result: [
[
{kind: 'atom', value: 'Et', multiplier: 3},
{kind: 'atom', value: 'C', multiplier: 6},
{kind: 'atom', value: 'H', multiplier: 15},
{kind: 'atom', value: 'N', multiplier: 1}
], [
{kind: 'atom', value: 'Cl', multiplier: 1},
{kind: 'atom', value: 'H', multiplier: 1}
{kind: 'atom', value: 'H', multiplier: 1},
{kind: 'atom', value: 'Cl', multiplier: 1}
]

@@ -44,0 +45,0 @@ ]

'use strict';
const Kind = require('../Kind');
const groups = require('chemical-elements/src/groupsObject.js');
const atomSorter = require('atom-sorter');
module.exports = function toParts(lines) {
/**
*
* @param {*} lines
* @param {object} options
* @param {boolean} [true] options.expand - Should we expand the groups
*/
module.exports = function toParts(lines, options = {}) {
const {
expand: shouldExpandGroups = true
} = options;
let parts = [];

@@ -11,3 +23,2 @@

parts.push(currentPart);
for (let line of lines) {

@@ -40,4 +51,6 @@ switch (line.kind) {

break;
case Kind.COMMENT: // we ignore comments to create the parts and canonized MF
break;
default:
throw new Error('Can not process mf having ', line.kind);
throw new Error('Can not process mf having: ' + line.kind);
}

@@ -47,4 +60,4 @@ previousKind = line.kind;

globalPartMultiplier(currentPart);
return combineAtoms(parts);
if (shouldExpandGroups) expandGroups(parts);
return combineAtomsIsotopesCharges(parts);
};

@@ -99,3 +112,27 @@

function combineAtoms(parts) {
function expandGroups(parts) {
for (let part of parts) {
let expanded = false;
for (let i = 0; i < part.lines.length; i++) {
let line = part.lines[i];
if (line.kind === Kind.ATOM) {
let group = groups[line.value];
if (group) {
expanded = true;
for (let element of group.elements) {
part.lines.push({
kind: 'atom',
value: element.symbol,
multiplier: line.multiplier * element.number
});
}
part.lines[i] = undefined;
}
}
}
if (expanded) part.lines = part.lines.filter((a) => a);
}
}
function combineAtomsIsotopesCharges(parts) {
let results = [];

@@ -107,8 +144,15 @@ for (let part of parts) {

// Kind.ATOM
{
let currentKey = '';
for (let key of part.keys) {
let currentKey = '';
for (let key of part.keys) {
if (key.key === Kind.CHARGE) {
if (currentKey !== key.key) {
currentKey = key.key;
result.push({
kind: Kind.CHARGE,
value: key.value.value * key.value.multiplier
});
} else {
result[result.length - 1].value += key.value.value * key.value.multiplier;
}
} else {
if (currentKey !== key.key) {
result.push(key.value);

@@ -119,3 +163,21 @@ } else {

}
currentKey = key.key;
}
result.sort((a, b) => {
if (a.kind === Kind.CHARGE) return 1;
if (b.kind === Kind.CHARGE) return -1;
let atomA = a.kind === Kind.ATOM ? a.value : a.value.atom;
let atomB = b.kind === Kind.ATOM ? b.value : b.value.atom;
if (atomA !== atomB) return atomSorter(atomA, atomB);
// same atome but some isotopes ...
if (a.kind === Kind.ATOM) return -1;
if (b.kind === Kind.ATOM) return 1;
if (a.kind === Kind.ISOTOPE) return -1;
if (b.kind === Kind.ISOTOPE) return 1;
if (a.kind === Kind.ISOTOPE_RATIO) return -1;
if (b.kind === Kind.ISOTOPE_RATIO) return 1;
return 0;
});
}

@@ -138,8 +200,14 @@ return results;

let key = [line.kind];
if (typeof line.value === 'string') {
key.push(line.value);
} else {
for (let prop of Object.keys(line.value).sort()) {
key.push(line.value[prop]);
}
switch (line.kind) {
case (Kind.CHARGE):
break;
default:
if (typeof line.value === 'string') {
key.push(line.value);
} else {
for (let prop of Object.keys(line.value).sort()) {
key.push(line.value[prop]);
}
}
}

@@ -146,0 +214,0 @@ return key.join('-');

Sorry, the diff of this file is not supported yet

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