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

chromatography

Package Overview
Dependencies
Maintainers
5
Versions
44
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

chromatography - npm Package Compare versions

Comparing version 4.1.0 to 4.1.1

537

lib/index.js

@@ -9,10 +9,10 @@ 'use strict';

var mlSpectraProcessing = require('ml-spectra-processing');
var mfParser = require('mf-parser');
var arrayMean = _interopDefault(require('ml-array-mean'));
var max = _interopDefault(require('ml-array-max'));
var IsotopicDistribution = _interopDefault(require('isotopic-distribution'));
var sum = _interopDefault(require('ml-array-sum'));
var median = _interopDefault(require('ml-array-median'));
var gsd = require('ml-gsd/src/gsd');
var broadenPeaks = require('ml-gsd/src/post/broadenPeaks');
var median = _interopDefault(require('ml-array-median'));
var sum = _interopDefault(require('ml-array-sum'));
var max = _interopDefault(require('ml-array-max'));
var IsotopicDistribution = _interopDefault(require('isotopic-distribution'));
var mfParser = require('mf-parser');
var arrayMean = _interopDefault(require('ml-array-mean'));
var Regression = _interopDefault(require('ml-regression-polynomial'));

@@ -25,25 +25,84 @@ var binarySearch = _interopDefault(require('binary-search'));

function filter(chromatogram, callback, options = {}) {
const { copy = false } = options;
if (copy) {
chromatogram = chromatogram.copy();
function applyLockMass(chromatogram, mfs, options = {}) {
const { oddReference = true, maxShift = 0.1 } = options;
// allows mf as string or array
if (typeof mfs === 'string') {
mfs = [mfs];
}
let times = chromatogram.getTimes();
let newTimes = [];
let indexToKeep = [];
for (let i = 0; i < times.length; i++) {
if (callback(i, times[i])) {
indexToKeep.push(i);
newTimes.push(times[i]);
// calculate the mass reference values
const referenceMass = mfs.map((mf) => {
let info = new mfParser.MF(mf).getInfo();
return info.observedMonoisotopicMass || info.monoisotopicMass;
});
const ms = chromatogram.getSeries('ms').data;
// check where is the reference values
let referenceIndexShift = Number(oddReference);
let msIndexShift = Number(!oddReference);
const newSize = ms.length >> 1;
let referencesCount = new Array(referenceMass.length).fill(0);
// applying the changes for all the spectra
let previousValidDifference = Number.MAX_VALUE;
let usingPreviousValidDifference = false;
for (let i = 0; i < newSize; i++) {
let massIndex = 2 * i + msIndexShift;
let referenceIndex = 2 * i + referenceIndexShift;
// calculate the difference between theory and experimental (the smallest)
let difference = Number.MAX_VALUE;
let closestIndex = -1;
for (let j = 0; j < referenceMass.length; j++) {
for (let k = 0; k < ms[referenceIndex][0].length; k++) {
if (
Math.abs(difference) >
Math.abs(referenceMass[j] - ms[referenceIndex][0][k])
) {
difference = referenceMass[j] - ms[referenceIndex][0][k];
closestIndex = j;
}
}
}
if (
Math.abs(difference) > maxShift &&
Math.abs(previousValidDifference) < maxShift
) {
difference = previousValidDifference;
usingPreviousValidDifference = true;
} else {
usingPreviousValidDifference = false;
}
// apply identified lock mass
if (Math.abs(difference) < maxShift) {
previousValidDifference = difference;
if (!usingPreviousValidDifference) {
if (closestIndex !== -1) {
referencesCount[closestIndex] += 1;
}
}
for (let m = 0; m < ms[massIndex][0].length; m++) {
ms[massIndex][0][m] += difference;
}
}
}
chromatogram.times = newTimes;
for (let key of chromatogram.getSeriesNames()) {
const series = chromatogram.getSeries(key);
series.keep(indexToKeep);
const referenceUsed = {
total: newSize,
totalFound: referencesCount.reduce((prev, current) => current + prev, 0),
mfs: {},
percent: 0,
};
for (let r = 0; r < referenceMass.length; r++) {
referenceUsed.mfs[mfs[r]] = referencesCount[r];
}
referenceUsed.percent =
(referenceUsed.totalFound / referenceUsed.total) * 100;
return chromatogram;
// remove the time and the mass spectra that contains the reference
chromatogram.filter((index) => index % 2 !== referenceIndexShift);
return referenceUsed;
}

@@ -138,66 +197,57 @@

function getPeaks(chromatogram, options = {}) {
const {
heightFilter = 2,
seriesName = 'tic',
broadenPeaksOptions = { factor: 1, overlap: false },
} = options;
function meanFilter(chromatogram, seriesName, options = {}) {
const { factor = 2 } = options;
const series = chromatogram.getSeries(seriesName).data;
const times = chromatogram.getTimes();
let series = chromatogram.getSeries(seriesName);
let filtered = [];
for (let i = 0; i < series.data.length; i++) {
filtered.push(applyFilter(series.data[i], factor));
}
// first peak selection
let peakList = gsd.gsd(times, series, {
noiseLevel: 0,
realTopDetection: false,
smoothY: true,
sgOptions: { windowSize: 5, polynomial: 2 },
heightFactor: 2,
boundaries: true,
});
// filter height by factor
let medianHeight = median(series);
return seriesFromArray(filtered);
}
peakList = peakList.filter((val) => val.height > medianHeight * heightFilter);
function applyFilter(series, factor) {
let filtered = [[], []];
if (series[1].length === 0) return filtered;
const meanIntensity = factor * arrayMean(series[1]);
for (let i = 0; i < series[0].length; i++) {
if (series[1][i] > meanIntensity) {
filtered[0].push(series[0][i]);
filtered[1].push(series[1][i]);
}
}
return filtered;
}
peakList.sort((a, b) => a.x - b.x);
function percentageFilter(chromatogram, seriesName, options = {}) {
const { percentage = 0.1 } = options;
if (broadenPeaksOptions) {
peakList = broadenPeaks.broadenPeaks(peakList, broadenPeaksOptions);
let series = chromatogram.getSeries(seriesName);
let filtered = [];
for (let i = 0; i < series.data.length; i++) {
filtered.push(applyFilter$1(series.data[i], percentage));
}
return peakList.map((peak) => ({
from: peak.from,
to: peak.to,
inflectionPoints: {
from: Math.min(peak.left.x, peak.right.x),
to: Math.max(peak.left.x, peak.right.x),
},
retentionTime: peak.x,
intensity: peak.y,
}));
return seriesFromArray(filtered);
}
function calculateTic(chromatogram) {
const ms = chromatogram.getSeries('ms');
const massSpectra = ms.data;
const tic = [];
for (const massSpectrum of massSpectra) {
if (massSpectrum[1].length > 0) {
tic.push(sum(massSpectrum[1]));
} else {
tic.push(0);
function applyFilter$1(series, percentage) {
let basePeak;
try {
basePeak = max(series[1]);
} catch (e) {
basePeak = 0;
}
let filtered = [[], []];
for (let i = 0; i < series[0].length; i++) {
if (series[1][i] > percentage * basePeak) {
filtered[0].push(series[0][i]);
filtered[1].push(series[1][i]);
}
}
return tic;
return filtered;
}
function calculateLength(chromatogram, seriesName) {
const series2D = chromatogram.getSeries(seriesName);
const spectra = series2D.data;
const length = spectra.map((spectrum) => spectrum[0].length);
return length;
}
/**

@@ -301,2 +351,144 @@ * Calculate bpc

function calculateLength(chromatogram, seriesName) {
const series2D = chromatogram.getSeries(seriesName);
const spectra = series2D.data;
const length = spectra.map((spectrum) => spectrum[0].length);
return length;
}
function calculateTic(chromatogram) {
const ms = chromatogram.getSeries('ms');
const massSpectra = ms.data;
const tic = [];
for (const massSpectrum of massSpectra) {
if (massSpectrum[1].length > 0) {
tic.push(sum(massSpectrum[1]));
} else {
tic.push(0);
}
}
return tic;
}
function merge(chromatogram, options = {}) {
const time = chromatogram.getTimes();
let { mergeThreshold = 0.3, seriesName = 'ms', range = {} } = options;
chromatogram.requiresSeries(seriesName);
let series = chromatogram.series[seriesName];
if (series.dimension !== 2) {
throw new Error(`The series "${seriesName}" is not of dimension 2`);
}
if (!range || range.from > time[time.length - 1] || range.to < time[0]) {
return { x: [], y: [] };
}
let { fromIndex, toIndex } = mlSpectraProcessing.X.getFromToIndex(time, range);
let result = mlSpectraProcessing.XY.toXYObject({
x: series.data[fromIndex][0],
y: series.data[fromIndex][1],
});
for (let i = fromIndex + 1; i <= toIndex; i++) {
let newData = mlSpectraProcessing.XY.toXYObject({
x: series.data[i][0],
y: series.data[i][1],
});
result = result.concat(newData);
result = mlSpectraProcessing.XYObject.sortX(result);
result = mlSpectraProcessing.XYObject.joinX(result, { xError: mergeThreshold });
}
result = {
...mlSpectraProcessing.XYObject.toXY(result),
from: {
index: fromIndex,
time: time[fromIndex],
},
to: {
index: toIndex,
time: time[toIndex],
},
};
return result;
}
function getPeaks(chromatogram, options = {}) {
const {
heightFilter = 2,
seriesName = 'tic',
broadenPeaksOptions = { factor: 1, overlap: false },
} = options;
const series = chromatogram.getSeries(seriesName).data;
const times = chromatogram.getTimes();
// first peak selection
let peakList = gsd.gsd(times, series, {
noiseLevel: 0,
realTopDetection: false,
smoothY: true,
sgOptions: { windowSize: 5, polynomial: 2 },
heightFactor: 2,
boundaries: true,
});
// filter height by factor
let medianHeight = median(series);
peakList = peakList.filter((val) => val.height > medianHeight * heightFilter);
peakList.sort((a, b) => a.x - b.x);
if (broadenPeaksOptions) {
peakList = broadenPeaks.broadenPeaks(peakList, broadenPeaksOptions);
}
return peakList.map((peak) => ({
from: peak.from,
to: peak.to,
inflectionPoints: {
from: Math.min(peak.left.x, peak.right.x),
to: Math.max(peak.left.x, peak.right.x),
},
retentionTime: peak.x,
intensity: peak.y,
}));
}
function filter(chromatogram, callback, options = {}) {
const { copy = false } = options;
if (copy) {
chromatogram = chromatogram.copy();
}
let times = chromatogram.getTimes();
let newTimes = [];
let indexToKeep = [];
for (let i = 0; i < times.length; i++) {
if (callback(i, times[i])) {
indexToKeep.push(i);
newTimes.push(times[i]);
}
}
chromatogram.times = newTimes;
for (let key of chromatogram.getSeriesNames()) {
const series = chromatogram.getSeries(key);
series.keep(indexToKeep);
}
return chromatogram;
}
function getClosestData(chromatogram, time, options = {}) {
const { seriesName = 'ms' } = options;
chromatogram.requiresSeries(seriesName);
let closest = chromatogram.getClosestTime(time);
return {
rt: chromatogram.getTimes()[closest],
index: closest,
data: chromatogram.getSeries(seriesName).data[closest],
};
}
function baselineCorrection(points, fromTo, kind) {

@@ -397,194 +589,2 @@ const deltaTime = points.x[fromTo.toIndex] - points.x[fromTo.fromIndex];

function merge(chromatogram, options = {}) {
const time = chromatogram.getTimes();
let { mergeThreshold = 0.3, seriesName = 'ms', range = {} } = options;
chromatogram.requiresSeries(seriesName);
let series = chromatogram.series[seriesName];
if (series.dimension !== 2) {
throw new Error(`The series "${seriesName}" is not of dimension 2`);
}
if (!range || range.from > time[time.length - 1] || range.to < time[0]) {
return { x: [], y: [] };
}
let { fromIndex, toIndex } = mlSpectraProcessing.X.getFromToIndex(time, range);
let result = mlSpectraProcessing.XY.toXYObject({
x: series.data[fromIndex][0],
y: series.data[fromIndex][1],
});
for (let i = fromIndex + 1; i <= toIndex; i++) {
let newData = mlSpectraProcessing.XY.toXYObject({
x: series.data[i][0],
y: series.data[i][1],
});
result = result.concat(newData);
result = mlSpectraProcessing.XYObject.sortX(result);
result = mlSpectraProcessing.XYObject.joinX(result, { xError: mergeThreshold });
}
result = {
...mlSpectraProcessing.XYObject.toXY(result),
from: {
index: fromIndex,
time: time[fromIndex],
},
to: {
index: toIndex,
time: time[toIndex],
},
};
return result;
}
function applyLockMass(chromatogram, mfs, options = {}) {
const { oddReference = true, maxShift = 0.1 } = options;
// allows mf as string or array
if (typeof mfs === 'string') {
mfs = [mfs];
}
// calculate the mass reference values
const referenceMass = mfs.map((mf) => {
let info = new mfParser.MF(mf).getInfo();
return info.observedMonoisotopicMass || info.monoisotopicMass;
});
const ms = chromatogram.getSeries('ms').data;
// check where is the reference values
let referenceIndexShift = Number(oddReference);
let msIndexShift = Number(!oddReference);
const newSize = ms.length >> 1;
let referencesCount = new Array(referenceMass.length).fill(0);
// applying the changes for all the spectra
let previousValidDifference = Number.MAX_VALUE;
let usingPreviousValidDifference = false;
for (let i = 0; i < newSize; i++) {
let massIndex = 2 * i + msIndexShift;
let referenceIndex = 2 * i + referenceIndexShift;
// calculate the difference between theory and experimental (the smallest)
let difference = Number.MAX_VALUE;
let closestIndex = -1;
for (let j = 0; j < referenceMass.length; j++) {
for (let k = 0; k < ms[referenceIndex][0].length; k++) {
if (
Math.abs(difference) >
Math.abs(referenceMass[j] - ms[referenceIndex][0][k])
) {
difference = referenceMass[j] - ms[referenceIndex][0][k];
closestIndex = j;
}
}
}
if (
Math.abs(difference) > maxShift &&
Math.abs(previousValidDifference) < maxShift
) {
difference = previousValidDifference;
usingPreviousValidDifference = true;
} else {
usingPreviousValidDifference = false;
}
// apply identified lock mass
if (Math.abs(difference) < maxShift) {
previousValidDifference = difference;
if (!usingPreviousValidDifference) {
if (closestIndex !== -1) {
referencesCount[closestIndex] += 1;
}
}
for (let m = 0; m < ms[massIndex][0].length; m++) {
ms[massIndex][0][m] += difference;
}
}
}
const referenceUsed = {
total: newSize,
totalFound: referencesCount.reduce((prev, current) => current + prev, 0),
mfs: {},
percent: 0,
};
for (let r = 0; r < referenceMass.length; r++) {
referenceUsed.mfs[mfs[r]] = referencesCount[r];
}
referenceUsed.percent =
(referenceUsed.totalFound / referenceUsed.total) * 100;
// remove the time and the mass spectra that contains the reference
chromatogram.filter((index) => index % 2 !== referenceIndexShift);
return referenceUsed;
}
function meanFilter(chromatogram, seriesName, options = {}) {
const { factor = 2 } = options;
let series = chromatogram.getSeries(seriesName);
let filtered = [];
for (let i = 0; i < series.data.length; i++) {
filtered.push(applyFilter(series.data[i], factor));
}
return seriesFromArray(filtered);
}
function applyFilter(series, factor) {
let filtered = [[], []];
if (series[1].length === 0) return filtered;
const meanIntensity = factor * arrayMean(series[1]);
for (let i = 0; i < series[0].length; i++) {
if (series[1][i] > meanIntensity) {
filtered[0].push(series[0][i]);
filtered[1].push(series[1][i]);
}
}
return filtered;
}
function percentageFilter(chromatogram, seriesName, options = {}) {
const { percentage = 0.1 } = options;
let series = chromatogram.getSeries(seriesName);
let filtered = [];
for (let i = 0; i < series.data.length; i++) {
filtered.push(applyFilter$1(series.data[i], percentage));
}
return seriesFromArray(filtered);
}
function applyFilter$1(series, percentage) {
let basePeak;
try {
basePeak = max(series[1]);
} catch (e) {
basePeak = 0;
}
let filtered = [[], []];
for (let i = 0; i < series[0].length; i++) {
if (series[1][i] > percentage * basePeak) {
filtered[0].push(series[0][i]);
filtered[1].push(series[1][i]);
}
}
return filtered;
}
function getClosestData(chromatogram, time, options = {}) {
const { seriesName = 'ms' } = options;
chromatogram.requiresSeries(seriesName);
let closest = chromatogram.getClosestTime(time);
return {
rt: chromatogram.getTimes()[closest],
index: closest,
data: chromatogram.getSeries(seriesName).data[closest],
};
}
class Chromatogram {

@@ -736,4 +736,5 @@ constructor(times, series) {

const {
seriesName = `ms ${targetMF} ${options.ionizations ||
'H+'} (${options.slotWidth || 1}, ${options.threshold || 0.05})`,
seriesName = `ms ${targetMF} ${options.ionizations || 'H+'} (${
options.slotWidth || 1
}, ${options.threshold || 0.05})`,
cache = false,

@@ -1259,3 +1260,3 @@ } = options;

function fromJcamp(jcamp) {
const data = jcampconverter.convert(jcamp, { chromatogram: true }).chromatogram;
const data = jcampconverter.convert(jcamp, { chromatogram: true }).flatten[0].chromatogram;
return fromJSON(data);

@@ -1262,0 +1263,0 @@ }

{
"name": "chromatography",
"version": "4.1.0",
"version": "4.1.1",
"description": "Tools for storing, searching and analyzing GC/MS data",

@@ -56,3 +56,3 @@ "main": "lib/index.js",

"eslint": "^6.8.0",
"eslint-config-cheminfo": "^2.0.5",
"eslint-config-cheminfo": "^3.0.0",
"eslint-plugin-import": "^2.20.2",

@@ -64,3 +64,3 @@ "eslint-plugin-jest": "^23.8.2",

"jest-matcher-deep-close-to": "^1.3.0",
"prettier": "^1.19.1",
"prettier": "^2.0.4",
"rollup": "^2.6.1",

@@ -75,3 +75,3 @@ "spectrum-generator": "^4.0.2",

"isotopic-distribution": "^1.1.8",
"jcampconverter": "^4.1.1",
"jcampconverter": "^5.0.2",
"mf-parser": "^1.1.5",

@@ -78,0 +78,0 @@ "ml-array-max": "^1.1.2",

import isAnyArray from 'is-any-array';
import { X } from 'ml-spectra-processing';
import { filter } from './util/filter';
import { seriesFromArray } from './seriesFromArray';
import { getPeaks } from './peaks/getPeaks';
import { calculateTic } from './ms/calculateTic';
import { calculateLength } from './ms/calculateLength';
import { applyLockMass } from './ms/applyLockMass';
import { meanFilter } from './filter/meanFilter';
import { percentageFilter } from './filter/percentageFilter';
import { calculateBpc } from './ms/calculateBpc';
import { calculateEic } from './ms/calculateEic';
import { calculateForMF } from './ms/calculateForMF';
import { integrate } from './util/integrate';
import { calculateLength } from './ms/calculateLength';
import { calculateTic } from './ms/calculateTic';
import { merge } from './ms/merge';
import { applyLockMass } from './ms/applyLockMass';
import { meanFilter } from './filter/meanFilter';
import { percentageFilter } from './filter/percentageFilter';
import { getPeaks } from './peaks/getPeaks';
import { seriesFromArray } from './seriesFromArray';
import { filter } from './util/filter';
import { getClosestData } from './util/getClosestData';
import { integrate } from './util/integrate';

@@ -165,4 +165,5 @@ export class Chromatogram {

const {
seriesName = `ms ${targetMF} ${options.ionizations ||
'H+'} (${options.slotWidth || 1}, ${options.threshold || 0.05})`,
seriesName = `ms ${targetMF} ${options.ionizations || 'H+'} (${
options.slotWidth || 1
}, ${options.threshold || 0.05})`,
cache = false,

@@ -169,0 +170,0 @@ } = options;

@@ -6,4 +6,4 @@ import { convert as converter } from 'jcampconverter';

export function fromJcamp(jcamp) {
const data = converter(jcamp, { chromatogram: true }).chromatogram;
const data = converter(jcamp, { chromatogram: true }).flatten[0].chromatogram;
return fromJSON(data);
}

@@ -0,4 +1,4 @@

import median from 'ml-array-median';
import { gsd } from 'ml-gsd/src/gsd';
import { broadenPeaks } from 'ml-gsd/src/post/broadenPeaks';
import median from 'ml-array-median';

@@ -5,0 +5,0 @@ export function getPeaks(chromatogram, options = {}) {

@@ -0,5 +1,5 @@

import { cosineSimilarity } from './ms/cosineSimilarity';
import { appendMass } from './peaks/appendMass';
import { getPeaks } from './peaks/getPeaks';
import { appendMass } from './peaks/appendMass';
import { vectorify } from './vectorify';
import { cosineSimilarity } from './ms/cosineSimilarity';

@@ -6,0 +6,0 @@ /**

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