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

emdb

Package Overview
Dependencies
Maintainers
0
Versions
134
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

emdb - npm Package Compare versions

Comparing version 3.2.2 to 3.3.0

lib/append/appendFragmentsInfo.d.ts

1416

lib/index.js

@@ -1,1273 +0,195 @@

'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var msSpectrum = require('ms-spectrum');
var mfFinder = require('mf-finder');
var mfGenerator = require('mf-generator');
var massFragmentation = require('mass-fragmentation');
var mfMatcher = require('mf-matcher');
var mfParser = require('mf-parser');
var mfUtilities = require('mf-utilities');
var chemicalGroups = require('chemical-groups');
var nucleotide = require('nucleotide');
var peptide = require('peptide');
var JSZip = require('jszip');
var crossFetch = require('cross-fetch');
var mfFromGoogleSheet = require('mf-from-google-sheet');
var isotopicDistribution = require('isotopic-distribution');
var peaksSimilarity = require('peaks-similarity');
var mlRegressionTheilSen = require('ml-regression-theil-sen');
var mlSpectraProcessing = require('ml-spectra-processing');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var JSZip__default = /*#__PURE__*/_interopDefaultLegacy(JSZip);
var crossFetch__default = /*#__PURE__*/_interopDefaultLegacy(crossFetch);
/**
*
* @param {object} experimentalSpectrum
* @param {object} database
* @param {object} [options={}]
* @param {function} [options.onStep] - Callback to do after each step
* @param {string} [options.ionizations=''] - string containing a comma separated list of modifications
* @param {number} [options.precision=100] - Allowed mass range based on precision
*/
async function appendFragmentsInfo(
experimentalSpectrum,
database,
options = {},
) {
const { ionizations, onStep, precision } = options;
if (!experimentalSpectrum) {
throw new Error('Experimental spectrum is not defined');
}
if (!database) {
throw new Error('Database is not defined');
}
const peaks = experimentalSpectrum.getPeaks({ sumValue: 1 });
for (let entry of database) {
const ranges = Object.keys(entry.atoms)
.map((atom) => `${atom}0-${entry.atoms[atom]}`)
.join(' ');
entry.fragments = {
nbFound: 0,
intensityFound: 0,
assignments: [],
};
for (let i = 0; i < peaks.length; i++) {
if (onStep) await onStep(i);
const peak = peaks[i];
const possibleMFs = await mfFinder.findMFs(peak.x, {
ionizations,
precision,
ranges,
});
if (possibleMFs.mfs.length > 0) {
entry.fragments.nbFound++;
entry.fragments.intensityFound += peak.y;
entry.fragments.assignments.push({
peak,
bestMF: possibleMFs.mfs[0],
});
}
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
}
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.EMDB = void 0;
const ms_spectrum_1 = require("ms-spectrum");
const appendFragmentsInfo_js_1 = require("./append/appendFragmentsInfo.js");
const fromArray_js_1 = require("./from/fromArray.js");
const fromMolecules_js_1 = require("./from/fromMolecules.js");
const fromMonoisotopicMass_js_1 = require("./from/fromMonoisotopicMass.js");
const fromNucleicSequence_js_1 = require("./from/fromNucleicSequence.js");
const fromPeptidicSequence_js_1 = require("./from/fromPeptidicSequence.js");
const fromRange_js_1 = require("./from/fromRange.js");
const loadCommercials_js_1 = require("./loadCommercials.js");
const loadGoogleSheet_js_1 = require("./loadGoogleSheet.js");
const loadKnapSack_js_1 = require("./loadKnapSack.js");
const search_js_1 = require("./search.js");
const searchMSEM_js_1 = require("./searchMSEM.js");
const searchSimilarity_js_1 = require("./searchSimilarity.js");
__exportStar(require("./massShifts.js"), exports);
__exportStar(require("./util/fetchJSON.js"), exports);
/**
* Generates a database 'generated' from an array of molecular formula
* @param {array} mfsArray - Array of string or Array of array containing the parts to combine
* @param {object} [options={}]
* @param {boolean} [options.estimate=false] - estimate the number of MF without filters
* @param {string} [options.databaseName='generated']
* @param {function} [options.onStep] - Callback to do after each step
* @param {number} [options.limit=10000000] - Maximum number of results
* @param {boolean} [options.canonizeMF=true] - Canonize molecular formula
* @param {boolean} [options.uniqueMFs=true] - Force canonization and make MF unique
* @param {string} [options.ionizations=''] - Comma separated list of ionizations (to charge the molecule)
* @param {object} [options.filter={}]
* @param {number} [options.filter.minMass=0] - Minimal monoisotopic mass
* @param {number} [options.filter.maxMass=+Infinity] - Maximal monoisotopic mass
* @param {number} [options.filter.minEM=0] - Minimal neutral monoisotopic mass
* @param {number} [options.filter.maxEM=+Infinity] - Maximal neutral monoisotopic mass
* @param {number} [options.filter.minMSEM=0] - Minimal observed monoisotopic mass
* @param {number} [options.filter.maxMSEM=+Infinity] - Maximal observed monoisotopic mass
* @param {number} [options.filter.minCharge=-Infinity] - Minimal charge
* @param {number} [options.filter.maxCharge=+Infinity] - Maximal charge
* @param {boolean} [options.filter.absoluteCharge=false] - If true, the charge is absolute (so between 0 and +Infinity by default)
* @param {object} [options.filter.unsaturation={}]
* @param {number} [options.filter.unsaturation.min=-Infinity] - Minimal unsaturation
* @param {number} [options.filter.unsaturation.max=+Infinity] - Maximal unsaturation
* @param {boolean} [options.filter.unsaturation.onlyInteger=false] - Integer unsaturation
* @param {boolean} [options.filter.unsaturation.onlyNonInteger=false] - Non integer unsaturation
* @param {object} [options.filter.atoms] - object of atom:{min, max}
* @param {function} [options.filter.callback] - a function to filter the MF
* @param {string} [options.filterFct] - A string representing a function
*
* @example
*
* const {EMDB} = require('emdb');
* let emdb = new EMDB();
* let array = ['C1-10', 'H1-10'];
* emdb.fromArray(array); // create a database 'generated' combining all possibilies
* console.log(emdb.get('generated').length); // 100
*
* @example
* const {EMDB} = require('emdb');
* let emdb = new EMDB();
* let array = ['C1-10 H1-10'];
* emdb.fromArray(array); // create a database 'generated' combining all possibilies
* console.log(emdb.get('generated').length); // 100
*
* @example
* const {EMDB} = require('emdb');
* let emdb = new EMDB();
* // in case of an array of array, one of the group is allwed
* let array = [['C1-10','H1-10'],'Cl0-1 Br0-1'];
* emdb.fromArray(array); // create a database 'generated' combining all possibilies
* console.log(emdb.get('generated').length); // 80
*
* @example
* <script src="https://www.lactame.com/lib/mass-tools/HEAD/mass-tools.js" />
* <script>
* let emdb = new MassTools.EMDB();
* let array = ['C1-10', 'H1-10'];
* emdb.fromArray(array); // create a database 'generated' combining all possibilities
* console.log(emdb.get('generated').length); // 100
* </script>
*
* // from the browser
* A class that deals with database of monoisotopic mass and molecular formula
*/
async function fromArray(mfsArray, options = {}) {
return mfGenerator.generateMFs(mfsArray, options);
}
/** * Generates a database 'monoisotopic' from a monoisotopic mass and various options
* @param {{smiles?:string,molecule?:string,idCode?:string}[]} entries - Array of object containing a property to recreate the molecule
* @param {import('openchemlib')} ocl - The OCL library
* @param {object} [options={}]
* @param {function} [options.onStep] - Callback to do after each step
* @param {boolean} [options.allowNeutral=true]
* @param {string} [options.ionizations=''] - string containing a comma separated list of modifications
* @param {number} [options.precision=100] - Allowed mass range based on precision
* @param {boolean} [options.groupResults=false] - Should we group the results if they have the same monoisotopic mass and experimental mass
* @param {object} [options.fragmentation={}]
* @param {object} [options.fragmentation.acyclic=false]
* @param {object} [options.fragmentation.cyclic=false]
* @param {object} [options.fragmentation.full=true]
* @param {import('mf-matcher').MSEMFilterOptions} [options.filter={}]
* @returns {Promise}
*/
async function fromMolecules(entries, ocl, options = {}) {
let {
onStep,
ionizations,
filter,
fragmentation = { acyclic: false, cyclic: false, full: true },
groupResults = false,
} = options;
ionizations = mfUtilities.preprocessIonizations(ionizations);
let results = [];
for (let i = 0; i < entries.length; i++) {
const entry = entries[i];
const molecule = getMolecule(entry, ocl);
if (!molecule) continue;
const { acyclic = false, cyclic = false, full = true } = fragmentation;
const allFragments = massFragmentation.fragment(molecule, {
acyclic,
cyclic,
full,
});
for (const oneFragment of allFragments) {
appendResults(results, oneFragment, {
entry,
ionizations,
filter,
});
if (onStep) onStep(i);
class EMDB {
constructor() {
this.databases = {};
this.experimentalSpectrum = undefined;
}
}
if (groupResults) {
results = groupFragmentationResults(results);
}
return results.sort((a, b) => a.em - b.em);
}
/**
* We could group the results and replace the property 'fragment' by 'fragments'
* @param {*} results
*/
function groupFragmentationResults(results) {
const sortedResults = results.slice().sort((a, b) => {
if (a.em !== b.em) {
return a.em - b.em;
/**
*
* @param {*} data
* @param {object} [options={}]
* @param {boolean} [options.normed=true] Should we normed (sum Y to 1) the experimental spectrum ?
* @param {number} [options.threshold=0.00025] Threshold used for peak picking
*/
setExperimentalSpectrum(data, options = {}) {
const { normed = true, threshold = 0.00025 } = options;
this.experimentalSpectrum = new ms_spectrum_1.Spectrum(data, { threshold });
if (normed) {
this.experimentalSpectrum.normedY();
}
return this.experimentalSpectrum;
}
if (a.ms.em !== b.ms.em) {
return a.ms.em - b.ms.em;
/**
* Add a new database using the KnapSack content
* @param {*} options
*/
async loadKnapSack(options = {}) {
const { databaseName = 'knapSack', forceReload = false } = options;
if (this.databases[databaseName] && !forceReload)
return;
this.databases[databaseName] = await (0, loadKnapSack_js_1.loadKnapSack)();
}
if (a.fragment.idCode < b.fragment.idCode) return -1;
return 1;
});
const groupedResults = [];
let currentResult = {};
for (let result of sortedResults) {
if (
result.em !== currentResult.em ||
result.ms.em !== currentResult.ms.em
) {
currentResult = { ...result };
currentResult.fragments = [
{
idCode: result.fragment.idCode,
type: result.fragment.type,
count: 1,
parents: [{ ...result.fragment.parent, count: 1 }],
},
];
delete currentResult.fragment;
groupedResults.push(currentResult);
} else {
const lastFragment =
currentResult.fragments[currentResult.fragments.length - 1];
if (lastFragment.idCode === result.fragment.idCode) {
lastFragment.count++;
if (
lastFragment.parents[lastFragment.parents.length - 1].idCode ===
result.fragment.parent.idCode
) {
lastFragment.parents[lastFragment.parents.length - 1].count++;
} else {
lastFragment.parents.push({ ...result.fragment.parent, count: 1 });
}
} else {
currentResult.fragments.push({
idCode: result.fragment.idCode,
type: result.fragment.type,
count: 1,
parents: [{ ...result.fragment.parent, count: 1 }],
});
}
/**
* Add a new database of 12000 commercial products
* @param {*} options
*/
async loadCommercials(options = {}) {
const { databaseName = 'commercials', forceReload = false } = options;
if (this.databases[databaseName] && !forceReload)
return;
this.databases[databaseName] = await (0, loadCommercials_js_1.loadCommercials)();
}
}
for (let group of groupedResults) {
group.fragments = group.fragments.sort((a, b) => b.count - a.count);
}
return groupedResults;
}
/**
*
* @param {object} entry
* @param {import('openchemlib')} ocl - The OCL library
*/
function getMolecule(entry, ocl) {
if (entry.idCode) {
return ocl.Molecule.fromIDCode(entry.idCode);
}
if (entry.ocl && entry.ocl.idCode) {
return ocl.Molecule.fromIDCode(entry.ocl.idCode);
}
if (entry.smiles) {
return ocl.Molecule.fromSmiles(entry.smiles);
}
if (entry.molfile) {
return ocl.Molecule.fromMolfile(entry.molfile);
}
return undefined;
}
function appendResults(results, oneFragment, options) {
const mf = oneFragment.mfInfo.mf;
const { ionizations, filter, entry } = options;
const mfInfo = new mfParser.MF(mf).getInfo();
for (let ionization of ionizations) {
const result = {
charge: mfInfo.charge,
em: mfInfo.monoisotopicMass,
mw: mfInfo.mass,
mf: mfInfo.mf,
ionization,
unsaturation: mfInfo.unsaturation,
atoms: mfInfo.atoms,
fragment: {
parent: {
...entry,
idCode: oneFragment.parentIDCode,
},
idCode: oneFragment.idCode,
type: oneFragment.fragmentType,
},
};
let match = mfMatcher.msemMatcher(result, filter);
if (!match) continue;
result.ms = match.ms;
result.ionization = match.ionization;
results.push(result);
}
}
/**
* Generates a database 'monoisotopic' from a monoisotopic mass and various options
* @param {number|string|array} masses - Monoisotopic mass
* @param {object} [options={}]
* @param {number} [options.maxIterations=10000000] - Maximum number of iterations
* @param {function} [options.onStep] - Callback to do after each step
* @param {boolean} [options.allowNeutral=true]
* @param {boolean} [options.uniqueMFs=true]
* @param {number} [options.limit=1000] - Maximum number of results
* @param {string} [options.ionizations=''] - string containing a comma separated list of modifications
* @param {string} [options.ranges='C0-100 H0-100 O0-100 N0-100'] - range of mfs to search
* @param {number} [options.precision=100] - Allowed mass range based on precision
* @param {object} [options.filter={}]
* @param {number} [options.filter.minCharge=-Infinity] - Minimal charge
* @param {number} [options.filter.maxCharge=+Infinity] - Maximal charge
* @param {boolean} [options.filter.absoluteCharge=false] - If true, the charge is absolute (so between 0 and +Infinity by default)
* @param {object} [options.filter.unsaturation={}]
* @param {number} [options.filter.unsaturation.min=-Infinity] - Minimal unsaturation
* @param {number} [options.filter.unsaturation.max=+Infinity] - Maximal unsaturation
* @param {boolean} [options.filter.unsaturation.onlyInteger=false] - Integer unsaturation
* @param {boolean} [options.filter.unsaturation.onlyNonInteger=false] - Non integer unsaturation
* @param {object} [options.filter.atoms] - object of atom:{min, max}
* @param {function} [options.filter.callback] - a function to filter the MF
* @returns {Promise}
*/
async function fromMonoisotopicMass(masses, options = {}) {
if (typeof masses === 'string') {
masses = masses.split(/[ ,;\r\n\t]/).map(Number);
}
if (typeof masses === 'number') {
masses = [masses];
}
let results = [];
for (let mass of masses) {
results.push(await mfFinder.findMFs(mass, options));
}
return {
mfs: results.map((entry) => entry.mfs).flat(),
info: {
numberMFEvaluated: results.reduce(
(sum, current) => (sum += current.info.numberMFEvaluated),
0,
),
numberResults: results.reduce(
(sum, current) => (sum += current.info.numberResults),
0,
),
},
};
}
/**
* Add a database starting from a peptidic sequence
*
* @param {string} [sequencesString] Sequence as a string of 1 letter or 3 letters code. Could also be a correct molecular formula respecting uppercase, lowercase
* @param {object} [options={}]
* @param {boolean} [options.estimate=false] - estimate the number of MF without filters
* @param {function} [options.onStep] - Callback to do after each step
* @param {number} [options.limit=100000]
* @param {string} [options.ionizations='']
* @param {object} [options.info={}]
* @param {string} [options.info.kind] - rna, ds-dna or dna. Default if contains U: rna, otherwise ds-dna
* @param {string} [options.info.fivePrime=monophosphate] - alcohol, monophosphate, diphosphate, triphosphate
* @param {string} [options.info.circular=false]
* @param {array} [options.mfsArray=[]]
* @param {object} [options.fragmentation={}] Object defining options for fragmentation
* @param {boolean} [options.fragmentation.a=false] If true allow fragments of type 'a'
* @param {boolean} [options.fragmentation.ab=false] If true allow fragments of type 'a' minus base
* @param {boolean} [options.fragmentation.b=false] If true allow fragments of type 'b'
* @param {boolean} [options.fragmentation.c=false] If true allow fragments of type 'c'
* @param {boolean} [options.fragmentation.d=false] If true allow fragments of type 'd'
* @param {boolean} [options.fragmentation.dh2o=false] If true allow fragments of type 'd' with water loss
* @param {boolean} [options.fragmentation.w=false] If true allow fragments of type 'w'
* @param {boolean} [options.fragmentation.x=false] If true allow fragments of type 'x'
* @param {boolean} [options.fragmentation.y=false] If true allow fragments of type 'y'
* @param {boolean} [options.fragmentation.z=false] If true allow fragments of type 'z'
* @param {boolean} [options.baseLoss=false] If true allow base loss at all the positions
*
* @param {object} [options.filter={}] Object defining options for molecular formula filter
* @param {number} [options.filter.minMass=0] - Minimal monoisotopic mass
* @param {number} [options.filter.maxMass=+Infinity] - Maximal monoisotopic mass
* @param {number} [options.filter.minEM=0] - Minimal neutral monoisotopic mass
* @param {number} [options.filter.maxEM=+Infinity] - Maximal neutral monoisotopic mass
* @param {number} [options.filter.minMSEM=0] - Minimal observed monoisotopic mass
* @param {number} [options.filter.maxMSEM=+Infinity] - Maximal observed monoisotopic mass
* @param {number} [options.filter.minCharge=-Infinity] - Minimal charge
* @param {number} [options.filter.maxCharge=+Infinity] - Maximal charge
* @param {boolean} [options.filter.absoluteCharge=false] - If true, the charge is absolute (so between 0 and +Infinity by default)
* @param {object} [options.filter.unsaturation={}]
* @param {number} [options.filter.unsaturation.min=-Infinity] - Minimal unsaturation
* @param {number} [options.filter.unsaturation.max=+Infinity] - Maximal unsaturation
* @param {boolean} [options.filter.unsaturation.onlyInteger=false] - Integer unsaturation
* @param {boolean} [options.filter.unsaturation.onlyNonInteger=false] - Non integer unsaturation
* @returns {Promise}
*/
async function fromNucleicSequence(sequencesString, options = {}) {
const {
mfsArray = [],
fragmentation = {},
filter = {},
ionizations = '',
info = {},
estimate = false,
limit = 100000,
onStep,
} = options;
let sequences = nucleotide.sequenceToMF(sequencesString, info).split('.');
let fragmentsArray = sequences.slice();
// calculate fragmentation
for (let i = 0; i < sequences.length; i++) {
let sequence = sequences[i];
let fragments = nucleotide.generateFragments(sequence, fragmentation);
if (i === 1) {
// complementary sequence
fragments = fragments.map((fragment) => fragment.replace(/\$/g, '$cmp-'));
get(databaseName) {
return this.databases[databaseName];
}
fragmentsArray = fragmentsArray.concat(fragments);
if (fragmentation.baseLoss) {
fragmentsArray = fragmentsArray.concat(nucleotide.baseLoss(sequence));
/**
* Load the contaminants database from a google sheet document
* @param {object} [options={}]
* @param {string} [options.databaseName='contaminants']
* @param {string} [options.forceReload=false]
*/
async loadContaminants(options = {}) {
const { databaseName = 'contaminants', forceReload = false } = options;
if (this.databases[databaseName] && !forceReload)
return;
this.databases[databaseName] = await (0, loadGoogleSheet_js_1.loadGoogleSheet)();
}
}
mfsArray.push(fragmentsArray);
let combined = await mfGenerator.generateMFs(mfsArray, {
ionizations,
filter,
uniqueMFs: false,
estimate,
onStep,
limit,
});
if (Array.isArray(combined)) {
// not an estimation
combined.forEach((result) => {
result.sequence = chemicalGroups.groupsToSequence(
result.parts.filter((part) => part).join(' '),
);
});
}
return combined;
}
function fragmentPeptide(sequence, options = {}) {
const { digestion = {}, protonation, fragmentation, protonationPH } = options;
sequence = peptide.sequenceToMF(sequence);
let fragmentsArray = [sequence];
// do we also have some digest fragments ?
if (digestion.enzyme) {
let digests = peptide.digestPeptide(sequence, digestion);
if (options.protonation) {
digests = peptide.chargePeptide(digests, {
pH: options.protonationPH,
});
/**
* Load a google sheet containing MF information
* @param {object} [options={}]
* @param {string} [options.databaseName='sheet']
* @param {string} [options.forceReload=false]
*/
async loadGoogleSheet(options = {}) {
const { databaseName = 'sheet', forceReload = false } = options;
if (this.databases[databaseName] && !forceReload)
return;
this.databases[databaseName] = await (0, loadGoogleSheet_js_1.loadGoogleSheet)();
}
fragmentsArray = fragmentsArray.concat(digests);
}
// allow neutral loss
if (options.allowNeutralLoss) {
sequence = peptide.allowNeutralLoss(sequence);
}
// apply protonation
if (protonation) {
sequence = peptide.chargePeptide(sequence, { pH: protonationPH });
}
// calculate fragmentation
let fragments = peptide.generatePeptideFragments(sequence, fragmentation);
fragmentsArray = fragmentsArray.concat(fragments);
return fragmentsArray;
}
/**
* Add a database starting from a peptidic sequence
*
* @param {string} [sequences] Sequence as a string of 1 letter or 3 letters code. Could also be a correct molecular formula respecting uppercase, lowercase. It can be comma separated if you have many peptide sequences
* @param {object} [options={}]
* @param {boolean} [options.estimate=false] - estimate the number of MF without filters
* @param {string} [options.ionizations='']
* @param {function} [options.onStep] - Callback to do after each step
* @param {array} [options.mfsArray=[]]
* @param {boolean} [options.protonation=false]
* @param {number} [options.protonationPH=7]
* @param {boolean} [options.allowNeutralLoss=false]
* @param {number} [options.limit=100000]
*
* @param {object} [options.digestion={}] Object defining options for digestion
* @param {number} [options.digestion.minMissed=0] Minimal number of allowed missed cleavage
* @param {number} [options.digestion.maxMissed=0] Maximal number of allowed missed cleavage
* @param {number} [options.digestion.minResidue=0] Minimal number of residues
* @param {number} [options.digestion.maxResidue=+Infinity] Maximal number of residues
* @param {string} [options.digestion.enzyme] Mandatory field containing the name of the enzyme among: chymotrypsin, trypsin, glucph4, glucph8, thermolysin, cyanogenbromide
*
* @param {object} [options.fragmentation={}] Object defining options for fragmentation
* @param {boolean} [options.fragmentation.a=false] If true allow fragments of type 'a'
* @param {boolean} [options.fragmentation.b=false] If true allow fragments of type 'b'
* @param {boolean} [options.fragmentation.c=false] If true allow fragments of type 'c'
* @param {boolean} [options.fragmentation.x=false] If true allow fragments of type 'x'
* @param {boolean} [options.fragmentation.y=false] If true allow fragments of type 'y'
* @param {boolean} [options.fragmentation.z=false] If true allow fragments of type 'z'
* @param {boolean} [options.fragmentation.ya=false] If true allow fragments of type 'ya'
* @param {boolean} [options.fragmentation.yb=false] If true allow fragments of type 'yb'
* @param {boolean} [options.fragmentation.yc=false] If true allow fragments of type 'yc'
* @param {boolean} [options.fragmentation.zc=false] If true allow fragments of type 'zc'
* @param {number} [options.fragmentation.minInternal=0] Minimal internal fragment length
* @param {number} [options.fragmentation.maxInternal=+Infinity] Maximal internal fragment length
*
* @param {object} [options.filter={}] Object defining options for molecular formula filter
* @param {number} [options.filter.precision=1000] - The precision on the experimental mass
* @param {number} [options.filter.targetMass] - Target mass, allows to calculate error and filter results
* @param {number[]} [options.filter.targetMasses] - Target masses: SORTED array of numbers
* @param {number[]} [options.filter.targetIntensities] - Target intensities: SORTED array of numbers
* @param {number} [options.filter.minEM=0] - Minimal neutral monoisotopic mass
* @param {number} [options.filter.maxEM=+Infinity] - Maximal neutral monoisotopic mass
* @param {number} [options.filter.minMSEM=0] - Minimal observed monoisotopic mass
* @param {number} [options.filter.maxMSEM=+Infinity] - Maximal observed monoisotopic mass
* @param {number} [options.filter.minCharge=-Infinity] - Minimal charge
* @param {number} [options.filter.maxCharge=+Infinity] - Maximal charge
* @param {boolean} [options.filter.absoluteCharge=false] - If true, the charge is absolute (so between 0 and +Infinity by default)
* @param {object} [options.filter.unsaturation={}]
* @param {number} [options.filter.unsaturation.min=-Infinity] - Minimal unsaturation
* @param {number} [options.filter.unsaturation.max=+Infinity] - Maximal unsaturation
* @param {boolean} [options.filter.unsaturation.onlyInteger=false] - Integer unsaturation
* @param {boolean} [options.filter.unsaturation.onlyNonInteger=false] - Non integer unsaturation
* @param {function} [options.filter.callback] - a function to filter the MF
* @returns {Promise}
*/
async function fromPeptidicSequence(sequences, options = {}) {
const {
digestion = {},
mfsArray: originalMFsArray = [],
allowNeutralLoss = false,
protonation = false,
protonationPH = 7,
fragmentation = {},
filter = {},
ionizations = '',
limit = 100000,
estimate = false,
onStep,
links = {},
} = options;
const hasLinked = sequences.includes('#');
const mfsArrayLinked = JSON.parse(JSON.stringify(originalMFsArray));
const mfsArrayUnlinked = JSON.parse(JSON.stringify(originalMFsArray));
const unlinked = [];
mfsArrayUnlinked.push(unlinked);
for (const sequence of sequences.split(/[,:]/)) {
let fragmentsArray = fragmentPeptide(sequence, {
digestion,
protonation,
fragmentation,
protonationPH,
allowNeutralLoss,
});
mfsArrayLinked.push(
fragmentsArray.filter((fragment) => fragment.includes('#')),
);
unlinked.push(
...fragmentsArray.filter((fragment) => !fragment.includes('#')),
);
}
let combined = await mfGenerator.generateMFs(mfsArrayUnlinked, {
ionizations,
filter,
estimate,
limit,
onStep,
links,
});
if (hasLinked) {
combined.push(
...(await mfGenerator.generateMFs(mfsArrayLinked, {
ionizations,
filter,
estimate,
limit,
onStep,
links,
})),
);
}
if (!estimate) {
combined.forEach((result) => {
result.sequence = chemicalGroups.groupsToSequence(
result.parts.filter((part) => part).join(' '),
);
});
}
return combined;
}
/**
* Generates a database 'generated' from an array of molecular formula
* @param {string} rangesString - a string representing the range to search
* @param {object} [options={}]
* @param {boolean} [options.estimate=false] - estimate the number of MF without filters
* @param {function} [options.onStep] - Callback to do after each step
* @param {string} [options.databaseName='generated']
* @param {number} [options.limit=100000] - Maximum number of results
* @param {boolean} [options.canonizeMF=true] - Canonize molecular formula
* @param {boolean} [options.uniqueMFs=true] - Force canonization and make MF unique
* @param {string} [options.ionizations=''] - Comma separated list of ionizations (to charge the molecule)
* @param {object} [options.filter={}]
* @param {number} [options.filter.minMass=0] - Minimal monoisotopic mass
* @param {number} [options.filter.maxMass=+Infinity] - Maximal monoisotopic mass
* @param {number} [options.filter.minEM=0] - Minimal neutral monoisotopic mass
* @param {number} [options.filter.maxEM=+Infinity] - Maximal neutral monoisotopic mass
* @param {number} [options.filter.minMSEM=0] - Minimal observed monoisotopic mass
* @param {number} [options.filter.maxMSEM=+Infinity] - Maximal observed monoisotopic mass
* @param {number} [options.filter.minCharge=-Infinity] - Minimal charge
* @param {number} [options.filter.maxCharge=+Infinity] - Maximal charge
* @param {boolean} [options.filter.absoluteCharge=false] - If true, the charge is absolute (so between 0 and +Infinity by default)
* @param {object} [options.filter.unsaturation={}]
* @param {number} [options.filter.unsaturation.min=-Infinity] - Minimal unsaturation
* @param {number} [options.filter.unsaturation.max=+Infinity] - Maximal unsaturation
* @param {boolean} [options.filter.unsaturation.onlyInteger=false] - Integer unsaturation
* @param {boolean} [options.filter.unsaturation.onlyNonInteger=false] - Non integer unsaturation
* @param {function} [options.filter.callback] - a function to filter the MF
* @param {object} [options.filter.atoms] - object of atom:{min, max}
*
* @returns {Promise} - list of possible molecular formula
*
* @example
* const {EMDB} = require('emdb');
* let emdb = new EMDB();
* // semi-columns separated for combination, comma for 'or'
* emdb.fromRange('C1-10, H1-10; Cl0-1 Br0-1'); // create a database 'generated' combining all possibilies
* console.log(emdb.get('generated').length); // 80
*/
async function fromRange(rangesString, options = {}) {
let ranges = rangesString.split(/ *[;\r\n] */);
for (let i = 0; i < ranges.length; i++) {
let range = ranges[i];
if (range.includes(',')) {
ranges[i] = range.split(/ *, */);
async loadTest() {
await this.fromArray(['C1-100'], {
databaseName: 'test',
ionizations: '+',
});
}
}
return mfGenerator.generateMFs(ranges, options);
}
async function fetchArrayBuffer(url) {
const result = await crossFetch__default["default"](url);
return result.arrayBuffer();
}
const loadingPromises$1 = {};
async function loadCommercials(options = {}) {
const {
url = 'https://couch.cheminfo.org/cheminfo-public/d2eb480198c80275a1d05dd3609414f9/upload/commercials.zip',
} = options;
if (!loadingPromises$1[url]) {
loadingPromises$1[url] = fetchArrayBuffer(url);
}
const buffer = await loadingPromises$1[url];
const jsZip = new JSZip__default["default"]();
let zip = await jsZip.loadAsync(buffer);
let fileData = await zip.files['commercials.json'].async('string');
let data = JSON.parse(fileData);
data.sort((a, b) => a.em - b.em);
return data;
}
async function loadGoogleSheet(options = {}) {
let {
refUUID = '1C_H9aiJyu9M9in7sHMOaz-d3Sv758rE72oLxEKH9ioA',
uuid = '1LrJCl9-xSZKhGA9Y8nKVkYwB-mEOHBkTXg5qYXeFpZY',
} = options;
if (options.uuid && !options.refUUID) refUUID = '';
let url = `https://googledocs.cheminfo.org/spreadsheets/d/${uuid}/export?format=tsv`;
let refURL = refUUID
? `https://googledocs.cheminfo.org/spreadsheets/d/${refUUID}/export?format=tsv`
: '';
let data = await mfFromGoogleSheet.mfFromGoogleSheet(url, refURL);
data.sort((a, b) => a.em - b.em);
return data;
}
const loadingPromises = {};
async function loadKnapSack(options = {}) {
const {
url = 'https://couch.cheminfo.org/cheminfo-public/d2eb480198c80275a1d05dd3609414f9/upload/ms.zip',
} = options;
if (!loadingPromises[url]) {
loadingPromises[url] = fetchArrayBuffer(url);
}
const buffer = await loadingPromises[url];
const jsZip = new JSZip__default["default"]();
let zip = await jsZip.loadAsync(buffer);
let fileData = await zip.files['ms.json'].async('string');
let data = JSON.parse(fileData);
data.forEach((d) => {
d.url = `http://kanaya.naist.jp/knapsack_jsp/information.jsp?word=${d.id}`;
});
data.sort((a, b) => a.em - b.em);
return data;
}
/**
Searching by various criteria. This mass will not take into account the mass
of the mass of the electron
* @param {object} [filter={}]
* @param {number} [filter.minMW=0] - Minimal molecular weight
* @param {number} [filter.maxMW=+Infinity] - Maximal molecular weight
* @param {number} [filter.minEM=0] - Minimal monoisotopic mass
* @param {number} [filter.maxEM=+Infinity] - Maximal monoisotopic mass
* @param {number} [filter.minCharge=-Infinity] - Minimal charge
* @param {number} [filter.maxCharge=+Infinity] - Maximal charge
* @param {boolean} [filter.absoluteCharge=false] - If true, the charge is absolute (so between 0 and +Infinity by default)
* @param {object} [filter.unsaturation={}]
* @param {number} [filter.unsaturation.min=-Infinity] - Minimal unsaturation
* @param {number} [filter.unsaturation.max=+Infinity] - Maximal unsaturation
* @param {boolean} [filter.unsaturation.onlyInteger=false] - Integer unsaturation
* @param {boolean} [filter.unsaturation.onlyNonInteger=false] - Non integer unsaturation
* @param {object} [filter.atoms] - object of atom:{min, max}
* @param {object} [options={}]
* @param {array} [options.databases] - an array containing the name of the databases so search, by default all
* @param {boolean} [options.flatten=false] - should we return the array as a flat result
*/
function search(emdb, filter, options = {}) {
let { databases = Object.keys(emdb.databases), flatten = false } = options;
let results = {};
for (let database of databases) {
results[database] = emdb.databases[database].filter((entry) =>
mfMatcher.generalMatcher(entry, filter),
);
}
if (flatten) {
let flattenResults = [];
for (let database of databases) {
for (let entry of results[database]) {
entry.database = database;
flattenResults.push(entry);
}
async loadNeutralTest(options = {}) {
const { maxC = 100 } = options;
await this.fromArray([`C1-${maxC}`], { databaseName: 'test' });
}
return flattenResults;
} else {
return results;
}
}
/**
Search for an experimental monoisotopic mass
* @param {number} msem - The observed monoisotopic mass
* @param {object} [options={}]
* @param {array} [options.databases] - an array containing the name of the databases so search, by default all
* @param {boolean} [options.flatten=false] - should we return the array as a flat result
* @param {string} [options.ionizations] - list the allowed ionizations possibilities
* @param {import('mf-matcher').MSEMFilterOptions} [options.filter={}]
*/
function searchMSEM(emdb, msem, options = {}) {
let filter = { ...(options.filter || {}), targetMass: msem };
let { databases = Object.keys(emdb.databases), flatten = false } = options;
let ionizations = mfUtilities.preprocessIonizations(options.ionizations);
let results = {};
for (let database of databases) {
results[database] = [];
}
for (let ionization of ionizations) {
filter.ionization = ionization;
for (let database of databases) {
for (let entry of emdb.databases[database]) {
let match = mfMatcher.msemMatcher(entry, filter);
if (match) {
results[database].push({
...entry,
ms: match.ms,
ionization: match.ionization,
});
}
}
async fromMonoisotopicMass(mass, options = {}) {
const { databaseName = 'monoisotopic', append = false } = options;
let result = await (0, fromMonoisotopicMass_js_1.fromMonoisotopicMass)(mass, options);
replaceOrAppend(this, databaseName, result.mfs, append);
return result;
}
}
if (flatten) {
let flattenResults = [];
for (let database of databases) {
for (let entry of results[database]) {
entry.database = database;
flattenResults.push(entry);
}
async fromArray(sequence, options = {}) {
const { databaseName = 'generated', append = false, estimate } = options;
const results = await (0, fromArray_js_1.fromArray)(sequence, options);
if (estimate)
return results;
replaceOrAppend(this, databaseName, results, append);
}
flattenResults.sort((a, b) => Math.abs(a.ms.ppm) - Math.abs(b.ms.ppm));
return flattenResults;
} else {
Object.keys(results).forEach((k) =>
results[k].sort((a, b) => Math.abs(a.ms.ppm) - Math.abs(b.ms.ppm)),
);
return results;
}
}
/**
Search for an experimental monoisotopic mass and calculate the similarity
* @param {object} [options={}]
* @param {array} [options.databases] - an array containing the name of the databases so search, by default all
* @param {boolean} [options.flatten] - should we return the array as a flat result
* @param {function} [options.onStep] - Callback to do after each step
* @param {string} [options.ionizations=''] - Comma separated list of ionizations (to charge the molecule)
* @param {object} [options.minSimilarity=0.5] - min similarity value
* @param {object} [options.filter={}]
* @param {boolean} [options.filter.forceIonization=false] - If true ignore existing ionizations
* @param {number} [options.filter.msem] - Observed monoisotopic mass in mass spectrometer
* @param {number} [options.filter.precision=1000] - The precision on the experimental mass
* @param {number} [options.filter.minCharge=-Infinity] - Minimal charge
* @param {number} [options.filter.maxCharge=+Infinity] - Maximal charge
* @param {boolean} [options.filter.absoluteCharge=false] - If true, the charge is absolute (so between 0 and +Infinity by default)
* @param {object} [options.filter.unsaturation={}]
* @param {number} [options.filter.unsaturation.min=-Infinity] - Minimal unsaturation
* @param {number} [options.filter.unsaturation.max=+Infinity] - Maximal unsaturation
* @param {boolean} [options.filter.unsaturation.onlyInteger=false] - Integer unsaturation
* @param {boolean} [options.filter.unsaturation.onlyNonInteger=false] - Non integer unsaturation
* @param {object} [options.filter.atoms] - object of atom:{min, max}
* @param {object} [options.filter.callback] - a function to filter the MF
* @param {object} [options.similarity={}]
* @param {number} [options.similarity.widthBottom]
* @param {number} [options.similarity.widthTop]
* @param {object} [options.similarity.widthFunction] - function called with mass that should return an object width containing top and bottom
* @param {object} [options.similarity.zone={}]
* @param {number} [options.similarity.zone.low=-0.5] - window shift based on observed monoisotopic mass
* @param {number} [options.similarity.zone.high=2.5] - to value for the comparison window
* @param {boolean} [options.similarity.zone.auto=false] - if true, low / high is determined based on the isotopic distribution and the threshold
* @param {string} [options.similarity.common]
* @param {number} [options.similarity.threshold=0.001] - when calculating similarity we only use the isotopic distribution with peaks over this relative threshold
* @param {number} [options.similarity.limit] - We may define the maximum number of peaks to keep
* @returns {Promise}
*/
async function searchSimilarity(emdb, options = {}) {
const { similarity = {}, minSimilarity = 0.5, filter = {}, onStep } = options;
let width = {
bottom: similarity.widthBottom,
top: similarity.widthTop,
};
if (
!emdb.experimentalSpectrum ||
!emdb.experimentalSpectrum.data.x.length > 0
) {
throw Error(
'You need to add an experimental spectrum first using setMassSpectrum',
);
}
let experimentalData = emdb.experimentalSpectrum.data;
let sumY = emdb.experimentalSpectrum.sumY();
// the result of emdb query will be stored in a property 'ms'
let results = emdb.searchMSEM(filter.msem, options);
let flatEntries = [];
if (!options.flatten) {
for (let database of Object.keys(results)) {
for (let entry of results[database]) {
flatEntries.push(entry);
}
async fromMolecules(entries, ocl, options = {}) {
const { databaseName = 'molecules', append = false } = options;
const results = await (0, fromMolecules_js_1.fromMolecules)(entries, ocl, options);
replaceOrAppend(this, databaseName, results, append);
}
} else {
flatEntries = results;
}
let { widthFunction, zone = {}, threshold = 0.001, limit } = similarity;
if (widthFunction && typeof widthFunction === 'string') {
// eslint-disable-next-line no-new-func
widthFunction = new Function('mass', widthFunction);
let checkTopBottom = widthFunction(123);
if (!checkTopBottom.bottom || !checkTopBottom.top) {
throw Error(
'widthFunction should return an object with bottom and top properties',
);
async fromRange(sequence, options = {}) {
const { databaseName = 'generated', append = false, estimate } = options;
const results = await (0, fromRange_js_1.fromRange)(sequence, options);
if (estimate)
return results;
replaceOrAppend(this, databaseName, results, append);
}
}
const { low = -0.5, high = 2.5, auto } = zone;
// we need to calculate the similarity of the isotopic distribution
let similarityProcessor = new peaksSimilarity.Comparator(similarity);
similarityProcessor.setPeaks1([experimentalData.x, experimentalData.y]);
for (let i = 0; i < flatEntries.length; i++) {
const entry = flatEntries[i];
if (onStep) await onStep(i);
if (widthFunction) {
width = widthFunction(entry.ms.em);
async fromPeptidicSequence(sequence, options = {}) {
const { databaseName = 'peptidic', append = false, estimate } = options;
const results = await (0, fromPeptidicSequence_js_1.fromPeptidicSequence)(sequence, options);
if (estimate)
return results;
replaceOrAppend(this, databaseName, results, append);
}
let isotopicDistribution$1 = new isotopicDistribution.IsotopicDistribution(entry.mf, {
allowNeutral: false,
ionizations: [entry.ionization],
fwhm: width.top / 2,
threshold,
limit,
});
let distribution = isotopicDistribution$1.getDistribution();
// we need to define the comparison zone that depends of the charge
let from, to;
if (auto) {
from = distribution.minX - 0.5;
to = distribution.maxX + 0.5;
similarityProcessor.setFromTo(from, to);
} else {
from = entry.ms.em + low / Math.abs(entry.ms.charge);
to = entry.ms.em + high / Math.abs(entry.ms.charge);
similarityProcessor.setFromTo(from, to);
/**
*
* @param {string} databaseName
* @param {object} [options={}]
* @param {number} [options.precision=100]
* @param {string} [options.ionizations='']
* @returns
*/
async appendFragmentsInfo(databaseName, options = {}) {
const database = this.databases[databaseName];
await (0, appendFragmentsInfo_js_1.appendFragmentsInfo)(this.experimentalSpectrum, database, options);
return database;
}
if (widthFunction) {
similarityProcessor.setTrapezoid(width.bottom, width.top);
async fromNucleicSequence(sequence, options = {}) {
const { databaseName = 'nucleic', append = false, estimate } = options;
const results = await (0, fromNucleicSequence_js_1.fromNucleicSequence)(sequence, options);
if (estimate)
return results;
replaceOrAppend(this, databaseName, results, append);
}
similarityProcessor.setPeaks2([distribution.xs, distribution.ys]);
let result = similarityProcessor.getSimilarity();
result.extractInfo1.from = from;
result.extractInfo1.to = to;
if (result.similarity > minSimilarity) {
entry.ms.similarity = {
value: result.similarity,
experimental: result.extract1,
theoretical: result.extract2,
difference: result.diff,
experimentalInfo: result.extractInfo1,
thereoticalInfo: result.extractInfo2,
quantity: result.extractInfo1.sum / sumY,
factor: result.extractInfo1.max / result.extractInfo2.max, // by how much we should mulitply the extrat2 to reach the spectrum
width,
};
listDatabases() {
return Object.keys(this.databases).sort();
}
}
if (!options.flatten) {
for (let database of Object.keys(results)) {
results[database] = results[database]
.filter((entry) => entry.ms.similarity)
.sort((a, b) => b.ms.similarity.value - a.ms.similarity.value);
for (let entry of results[database]) {
flatEntries.push(entry);
}
getInfo() {
return {
databases: Object.keys(this.databases)
.sort()
.map((key) => {
return { name: key, nbEntries: this.databases[key].length };
}),
};
}
} else {
results = results
.filter((entry) => entry.ms.similarity)
.sort((a, b) => b.ms.similarity.value - a.ms.similarity.value);
}
return results;
}
/**
* Calculates a function that allows post-calibration on mass spectra based on the error in assignment
* @param {*} similarities
* @param {object} [options={}]
* @returns
*/
function massShifts(similarities, options = {}) {
const { minSimilarity = 0.95, minLength = 10 } = options;
let results = [];
if (!Array.isArray(similarities)) {
for (let key of results) {
for (let entry of results[key]) {
results.push(entry);
}
search(filter, options = {}) {
return (0, search_js_1.search)(this, filter, options);
}
} else {
results = similarities;
}
results = results.filter(
(result) =>
result.ms &&
result.ms.similarity &&
result.ms.similarity.value > minSimilarity,
);
if (results.length < minLength) {
throw new Error(
`X rescale can not be applied. We need at least ${minLength} peaks with over ${Math.round(
minSimilarity * 100,
)}% similarity`,
);
}
const data = results
.map((result) => {
return {
em: result.ms.em,
delta: result.ms.delta,
};
})
.sort((a, b) => a.em - b.em);
let shifts = { x: [], y: [] };
data.forEach((datum) => {
shifts.x.push(Number(datum.em));
shifts.y.push(Number(datum.delta));
});
const regression = new mlRegressionTheilSen.TheilSenRegression(shifts.x, shifts.y);
let minX = mlSpectraProcessing.xMinValue(shifts.x);
let maxX = mlSpectraProcessing.xMaxValue(shifts.x);
let shiftsPPM = { x: shifts.x, y: [] };
data.forEach((datum) => {
shiftsPPM.y.push(Number((datum.delta / datum.em) * 1e6));
});
let regressionChart = { x: [], y: [] };
for (let i = minX; i < maxX; i += (maxX - minX) / 1000) {
regressionChart.x.push(i);
regressionChart.y.push(regression.predict(i));
}
return {
shifts,
shiftsPPM,
fit: regressionChart,
score: regression.score(shifts.x, shifts.y),
predictFct: regression.predict.bind(regression),
tex: regression.toLaTeX(3),
slope: regression.slope,
intercept: regression.intercept,
predictFctString: `${regression.slope} * mass + ${regression.intercept}`,
};
}
async function fetchJSON(url) {
const result = await crossFetch__default["default"](url);
return result.json();
}
/**
* A class that deals with database of monoisotopic mass and molecular formula
*/
class EMDB {
constructor() {
this.databases = {};
this.experimentalSpectrum = undefined;
}
/**
*
* @param {*} data
* @param {object} [options={}]
* @param {boolean} [options.normed=true] Should we normed (sum Y to 1) the experimental spectrum ?
* @param {number} [options.threshold=0.00025] Threshold used for peak picking
*/
setExperimentalSpectrum(data, options = {}) {
const { normed = true, threshold = 0.00025 } = options;
this.experimentalSpectrum = new msSpectrum.Spectrum(data, { threshold });
if (normed) {
this.experimentalSpectrum.normedY();
searchMSEM(filter, options = {}) {
return (0, searchMSEM_js_1.searchMSEM)(this, filter, options);
}
return this.experimentalSpectrum;
}
/**
* Add a new database using the KnapSack content
* @param {*} options
*/
async loadKnapSack(options = {}) {
const { databaseName = 'knapSack', forceReload = false } = options;
if (this.databases[databaseName] && !forceReload) return;
this.databases[databaseName] = await loadKnapSack();
}
/**
* Add a new database of 12000 commercial products
* @param {*} options
*/
async loadCommercials(options = {}) {
const { databaseName = 'commercials', forceReload = false } = options;
if (this.databases[databaseName] && !forceReload) return;
this.databases[databaseName] = await loadCommercials();
}
get(databaseName) {
return this.databases[databaseName];
}
/**
* Load the contaminants database from a google sheet document
* @param {object} [options={}]
* @param {string} [options.databaseName='contaminants']
* @param {string} [options.forceReload=false]
*/
async loadContaminants(options = {}) {
const { databaseName = 'contaminants', forceReload = false } = options;
if (this.databases[databaseName] && !forceReload) return;
this.databases[databaseName] = await loadGoogleSheet();
}
/**
* Load a google sheet containing MF information
* @param {object} [options={}]
* @param {string} [options.databaseName='sheet']
* @param {string} [options.forceReload=false]
*/
async loadGoogleSheet(options = {}) {
const { databaseName = 'sheet', forceReload = false } = options;
if (this.databases[databaseName] && !forceReload) return;
this.databases[databaseName] = await loadGoogleSheet();
}
async loadTest() {
await this.fromArray(['C1-100'], {
databaseName: 'test',
ionizations: '+',
});
}
async loadNeutralTest(options = {}) {
const { maxC = 100 } = options;
await this.fromArray([`C1-${maxC}`], { databaseName: 'test' });
}
async fromMonoisotopicMass(mass, options = {}) {
const { databaseName = 'monoisotopic', append = false } = options;
let result = await fromMonoisotopicMass(mass, options);
replaceOrAppend(this, databaseName, result.mfs, append);
return result;
}
async fromArray(sequence, options = {}) {
const { databaseName = 'generated', append = false, estimate } = options;
const results = await fromArray(sequence, options);
if (estimate) return results;
replaceOrAppend(this, databaseName, results, append);
}
async fromMolecules(entries, ocl, options = {}) {
const { databaseName = 'molecules', append = false } = options;
const results = await fromMolecules(entries, ocl, options);
replaceOrAppend(this, databaseName, results, append);
}
async fromRange(sequence, options = {}) {
const { databaseName = 'generated', append = false, estimate } = options;
const results = await fromRange(sequence, options);
if (estimate) return results;
replaceOrAppend(this, databaseName, results, append);
}
async fromPeptidicSequence(sequence, options = {}) {
const { databaseName = 'peptidic', append = false, estimate } = options;
const results = await fromPeptidicSequence(sequence, options);
if (estimate) return results;
replaceOrAppend(this, databaseName, results, append);
}
/**
*
* @param {string} databaseName
* @param {object} [options={}]
* @param {number} [options.precision=100]
* @param {string} [options.ionizations='']
* @returns
*/
async appendFragmentsInfo(databaseName, options = {}) {
const database = this.databases[databaseName];
await appendFragmentsInfo(this.experimentalSpectrum, database, options);
return database;
}
async fromNucleicSequence(sequence, options = {}) {
const { databaseName = 'nucleic', append = false, estimate } = options;
const results = await fromNucleicSequence(sequence, options);
if (estimate) return results;
replaceOrAppend(this, databaseName, results, append);
}
listDatabases() {
return Object.keys(this.databases).sort();
}
getInfo() {
return {
databases: Object.keys(this.databases)
.sort()
.map((key) => {
return { name: key, nbEntries: this.databases[key].length };
}),
};
}
search(filter, options = {}) {
return search(this, filter, options);
}
searchMSEM(filter, options = {}) {
return searchMSEM(this, filter, options);
}
searchSimilarity(options = {}) {
return searchSimilarity(this, options);
}
searchSimilarity(options = {}) {
return (0, searchSimilarity_js_1.searchSimilarity)(this, options);
}
}
exports.EMDB = EMDB;
function replaceOrAppend(emdb, databaseName, results, append = false) {
if (!emdb.databases[databaseName] || !append) {
emdb.databases[databaseName] = results;
return;
}
emdb.databases[databaseName] = emdb.databases[databaseName].concat(results);
if (!emdb.databases[databaseName] || !append) {
emdb.databases[databaseName] = results;
return;
}
emdb.databases[databaseName] = emdb.databases[databaseName].concat(results);
}
exports.EMDB = EMDB;
exports.fetchJSON = fetchJSON;
exports.massShifts = massShifts;
{
"name": "emdb",
"version": "3.2.2",
"version": "3.3.0",
"description": "Database manager for exact mass query",

@@ -23,28 +23,28 @@ "main": "lib/index.js",

"dependencies": {
"chemical-elements": "^2.0.4",
"chemical-groups": "^2.1.1",
"chemical-elements": "^2.1.0",
"chemical-groups": "^2.2.0",
"cross-fetch": "^4.0.0",
"isotopic-distribution": "^3.1.3",
"isotopic-distribution": "^3.2.0",
"jszip": "^3.10.1",
"mass-fragmentation": "^1.9.4",
"mf-finder": "^3.3.1",
"mf-from-google-sheet": "^3.0.7",
"mf-generator": "^3.2.1",
"mf-matcher": "^3.1.1",
"mf-parser": "^3.1.1",
"mf-utilities": "^3.1.1",
"mass-fragmentation": "^1.10.0",
"mf-finder": "^3.4.0",
"mf-from-google-sheet": "^3.1.0",
"mf-generator": "^3.3.0",
"mf-matcher": "^3.2.0",
"mf-parser": "^3.2.0",
"mf-utilities": "^3.2.0",
"ml-regression-theil-sen": "^3.0.0",
"ml-spectra-processing": "^14.5.0",
"ms-spectrum": "^3.5.2",
"nucleotide": "^3.0.3",
"openchemlib-utils": "^5.19.1",
"ml-spectra-processing": "^14.5.1",
"ms-spectrum": "^3.6.0",
"nucleotide": "^3.1.0",
"openchemlib-utils": "^6.0.1",
"peaks-similarity": "^3.1.1",
"peptide": "^2.1.2"
"peptide": "^2.2.0"
},
"devDependencies": {
"jest-matcher-deep-close-to": "^3.0.2",
"openchemlib": "^8.10.0",
"openchemlib": "^8.14.0",
"xy-parser": "^5.0.5"
},
"gitHead": "11531f8e222bd2a964a518a2fa14bf4d42c2507e"
"gitHead": "28dae91d3b42556a23097ee08acfe4061f276ed0"
}
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