isotopic-distribution
Advanced tools
Comparing version 0.5.6 to 0.5.8
{ | ||
"name": "isotopic-distribution", | ||
"version": "0.5.6", | ||
"version": "0.5.8", | ||
"description": "Calculate the isotopic distribution of a molecular formula", | ||
@@ -21,7 +21,7 @@ "main": "src/index.js", | ||
"dependencies": { | ||
"chemical-elements": "^0.5.2", | ||
"mf-parser": "^0.5.2", | ||
"mf-utilities": "^0.5.2", | ||
"spectrum-generator": "^1.0.1" | ||
"chemical-elements": "^0.5.8", | ||
"mf-parser": "^0.5.8", | ||
"mf-utilities": "^0.5.8", | ||
"spectrum-generator": "^1.1.0" | ||
} | ||
} |
@@ -8,9 +8,8 @@ 'use strict'; | ||
it('create distribution of C1 and getGaussian', () => { | ||
let isotopicDistribution = new IsotopicDistribution('C'); | ||
let isotopicDistribution = new IsotopicDistribution('C', { fwhm: 0.1 }); | ||
let gaussian = isotopicDistribution.getGaussian({ | ||
from: 11.00, | ||
to: 13.00, | ||
getWidth: () => 0.1, | ||
pointsPerUnit: 10, | ||
}); | ||
expect(gaussian.x).toHaveLength(201); | ||
expect(Math.min(...gaussian.x)).toBe(11); | ||
@@ -17,0 +16,0 @@ expect(Math.max(...gaussian.x)).toBe(13); |
@@ -13,2 +13,64 @@ 'use strict'; | ||
it('create distribution for multiplepart, C.C2', () => { | ||
let isotopicDistribution = new IsotopicDistribution('C.C2'); | ||
let distribution = isotopicDistribution.getDistribution(); | ||
expect(distribution.array).toMatchObject([{ x: 12, y: 0.9893 }, | ||
{ x: 13.00335483507, y: 0.0107 }, | ||
{ x: 24, y: 0.9787144899999999 }, | ||
{ x: 25.00335483507, y: 0.02117102 }, | ||
{ x: 26.00670967014, y: 0.00011448999999999998 }] | ||
); | ||
}); | ||
it('create distribution for multiplepart, C.C2.C3', () => { | ||
let isotopicDistribution = new IsotopicDistribution('C.C2.C3'); | ||
let distribution = isotopicDistribution.getDistribution(); | ||
expect(distribution.array.reduce((e, p) => (e += p.y), 0)).toBeCloseTo(3, 5); | ||
}); | ||
it('create distribution for charged multiplepart, C+.(C+)2', () => { | ||
let isotopicDistribution = new IsotopicDistribution('C+.(C+)2'); | ||
let distribution = isotopicDistribution.getDistribution(); | ||
expect(distribution.array).toMatchObject( | ||
[ | ||
{ x: 11.99945142009093, y: 1.9680144899999998 }, | ||
{ x: 12.501128837625929, y: 0.02117102 }, | ||
{ x: 13.00280625516093, y: 0.01081449 } | ||
] | ||
); | ||
}); | ||
it('getParts of isotopic distribution', () => { | ||
let isotopicDistribution = new IsotopicDistribution('C', { | ||
ionizations: 'H+' | ||
}); | ||
let parts = isotopicDistribution.getParts(); | ||
expect(parts[0].ms.em).toBeCloseTo(13.00727645232093, 5); | ||
}); | ||
it('create distribution for many ionizations, C + (+, ++)', () => { | ||
let isotopicDistribution = new IsotopicDistribution('C', { ionizations: '+,++' }); | ||
let distribution = isotopicDistribution.getDistribution(); | ||
expect(distribution.array).toMatchObject( | ||
[ | ||
{ x: 5.99945142009093, y: 0.9893 }, | ||
{ x: 6.50112883762593, y: 0.0107 }, | ||
{ x: 11.99945142009093, y: 0.9893 }, | ||
{ x: 13.00280625516093, y: 0.0107 } | ||
] | ||
); | ||
}); | ||
it('create distribution for many ionizations, C + H+', () => { | ||
let isotopicDistribution = new IsotopicDistribution('C', { ionizations: 'H+' }); | ||
let distribution = isotopicDistribution.getDistribution(); | ||
expect(distribution.array).toMatchObject( | ||
[ | ||
{ x: 13.00727645232093, y: 0.9893 }, | ||
{ x: 14.01063128739093, y: 0.0107 } | ||
] | ||
); | ||
}); | ||
it('create distribution of C10 and getXY', () => { | ||
@@ -78,3 +140,15 @@ let isotopicDistribution = new IsotopicDistribution('C10'); | ||
it('create distribution with no elements Ru0', () => { | ||
let isotopicDistribution = new IsotopicDistribution('Ru0'); | ||
let distribution = isotopicDistribution.getDistribution(); | ||
expect(distribution.array).toMatchObject([{ x: 0, y: 1 }]); | ||
}); | ||
it('create distribution with null elements', () => { | ||
let isotopicDistribution = new IsotopicDistribution('CRu0C'); | ||
let distribution = isotopicDistribution.getDistribution(); | ||
expect(distribution.array[0].x).toBe(24); | ||
}); | ||
}); |
@@ -76,2 +76,14 @@ 'use strict'; | ||
/** | ||
* Appen another distribution to the current distribution | ||
* @param {*} distribution | ||
*/ | ||
Distribution.prototype.append = function append(distribution) { | ||
for (let item of distribution.array) { | ||
this.array.push(item); | ||
} | ||
this.xSorted = false; | ||
this.ySorted = false; | ||
}; | ||
Distribution.prototype.sortX = require('./utils/sortX.js'); | ||
@@ -78,0 +90,0 @@ Distribution.prototype.sortY = require('./utils/sortY.js'); |
@@ -10,5 +10,16 @@ 'use strict'; | ||
const MF = require('mf-parser').MF; | ||
const preprocessIonizations = require('mf-utilities/src/preprocessIonizations'); | ||
const getMsInfo = require('mf-utilities/src/getMsInfo'); | ||
/** | ||
* An object containing two arrays | ||
* @typedef {object} XY | ||
* @property {Array<number>} x - The x array | ||
* @property {Array<number>} y - The y array | ||
*/ | ||
class IsotopicDistribution { | ||
/** | ||
@@ -18,17 +29,39 @@ * Class that manage isotopic distribution | ||
* @param {object} [options={}] | ||
* @param {number} [fwhm=0.001] - Amount of Dalton under which 2 peaks are joined | ||
* @param {string} [options.ionizations=''] - string containing a comma separated list of modifications | ||
* @param {number} [options.fwhm=0.01] - Amount of Dalton under which 2 peaks are joined | ||
* @param {number} [options.maxLines=5000] - Maximal number of lines during calculations | ||
* @param {number} [options.minY=1e-8] - Minimal signal height during calculations | ||
*/ | ||
constructor(mf, options = {}) { | ||
this.ionizations = preprocessIonizations(options.ionizations); | ||
this.mf = new MF(mf); | ||
this.isotopesInfo = this.mf.getIsotopesInfo(); | ||
this.charge = this.isotopesInfo.charge; | ||
this.absoluteCharge = Math.abs(this.isotopesInfo.charge); | ||
this.cache = {}; | ||
this.mfInfo = this.mf.getInfo(); | ||
let parts = this.mfInfo.parts || [this.mfInfo]; | ||
this.parts = []; | ||
for (let partOriginal of parts) { // we calculate informations for each part | ||
for (const ionization of this.ionizations) { | ||
let part = JSON.parse(JSON.stringify(partOriginal)); | ||
part.em = part.monoisotopicMass; // TODO: To remove !!! we change the name !? | ||
part.isotopesInfo = (new MF(part.mf)).getIsotopesInfo(); | ||
part.confidence = 0; | ||
part.ionization = ionization; | ||
part.ms = getMsInfo(part, { | ||
ionization, | ||
}); | ||
this.parts.push(part); | ||
} | ||
} | ||
this.options = options; | ||
this.fwhm = options.fwhm || 0.001; | ||
this.confidence = 0; | ||
this.fwhm = options.fwhm || 0.01; | ||
this.minY = options.minY || 1e-8; | ||
this.maxLines = options.maxLines || 5000; | ||
} | ||
getParts() { | ||
return this.parts; | ||
} | ||
/** | ||
* @return {Distribution} returns the internal object that contains the isotopic distribution | ||
* @return {Distribution} returns the total distribution (for all parts) | ||
*/ | ||
@@ -38,34 +71,60 @@ | ||
let options = { | ||
threshold: this.fwhm | ||
maxLines: this.maxLines, | ||
minY: this.minY, | ||
deltaX: this.fwhm, | ||
}; | ||
if (this.cache.distribution) return this.cache.distribution; | ||
let totalDistribution = new Distribution([{ x: 0, y: 1 }]); | ||
let finalDistribution; | ||
this.confidence = 0; | ||
for (let i = 0; i < this.parts.length; i++) { | ||
let part = this.parts[i]; | ||
let totalDistribution = new Distribution([{ x: 0, y: 1 }]); | ||
for (let isotope of this.isotopesInfo.isotopes) { | ||
let isotopeDistribution = new Distribution(isotope.distribution); | ||
isotopeDistribution.power(isotope.number, options); | ||
totalDistribution.multiply(isotopeDistribution, options); | ||
} | ||
this.cache.distribution = totalDistribution; | ||
this.confidence = this.cache.distribution.array.reduce((sum, value) => (sum + value.y), 0); | ||
for (let isotope of part.isotopesInfo.isotopes) { | ||
if (isotope.number) { | ||
let isotopeDistribution = new Distribution(isotope.distribution); | ||
isotopeDistribution.power(isotope.number, options); | ||
totalDistribution.multiply(isotopeDistribution, options); | ||
} | ||
} | ||
this.confidence += totalDistribution.array.reduce((sum, value) => (sum + value.y), 0); | ||
// we finally deal with the charge | ||
if (this.isotopesInfo.charge) { | ||
this.cache.distribution.array.forEach((e) => { | ||
e.x = (e.x - ELECTRON_MASS * this.charge) / this.absoluteCharge; | ||
}); | ||
// we finally deal with the charge | ||
let charge = part.isotopesInfo.charge + part.ionization.charge; | ||
let absoluteCharge = Math.abs(charge); | ||
if (charge) { | ||
totalDistribution.array.forEach((e) => { | ||
e.x = (e.x + part.ionization.em - ELECTRON_MASS * charge) / absoluteCharge; | ||
}); | ||
} | ||
if (i === 0) { | ||
finalDistribution = totalDistribution; | ||
} else { | ||
finalDistribution.append(totalDistribution); | ||
} | ||
} | ||
finalDistribution.join(this.fwhm); | ||
this.confidence /= this.parts.length; | ||
return finalDistribution; | ||
} | ||
return this.cache.distribution; | ||
getCSV() { | ||
return this.getText(','); | ||
} | ||
getTSV() { | ||
return this.getText('\t'); | ||
} | ||
/** | ||
* An object containing two arrays | ||
* @typedef {object} XY | ||
* @property {Array<number>} x - The x array | ||
* @property {Array<number>} y - The y array | ||
*/ | ||
getText(delimiter) { | ||
let points = this.getDistribution().array; | ||
let csv = []; | ||
for (let point of points) { | ||
csv.push(`${point.x.toFixed(5)}${delimiter}${(point.y * 100).toFixed(3)}`); | ||
} | ||
return csv.join('\n'); | ||
} | ||
/** | ||
* Returns the isotopic distirubtion | ||
* @return {XY} an object containing 2 properties: x:[] and y:[] | ||
@@ -88,5 +147,11 @@ */ | ||
/** | ||
* Returns the isotopic distirubtion as the sum of gaussians | ||
* @return {XY} isotopic distribution as an object containing 2 properties: x:[] and y:[] | ||
*/ | ||
getGaussian(options = {}) { | ||
let distribution = this.getDistribution(); | ||
let points = distribution.array; | ||
let pointsPerUnit = 10 / this.fwhm; | ||
if (points.length === 0) return []; | ||
@@ -96,4 +161,5 @@ let gaussianOptions = { | ||
end: Math.ceil(options.to || distribution.maxX + 10), | ||
pointsPerUnit: options.pointsPerUnit || 10, | ||
getWidth: options.getWidth ? options.getWidth : () => 0.1, | ||
pointsPerUnit, | ||
getWidth: options.getWidth ? options.getWidth : () => this.fwhm, | ||
maxSize: options.maxSize | ||
}; | ||
@@ -100,0 +166,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
27029
24
680
Updatedchemical-elements@^0.5.8
Updatedmf-parser@^0.5.8
Updatedmf-utilities@^0.5.8
Updatedspectrum-generator@^1.1.0