Spectrum

Class dealing with mass spectra and peak picking

new Spectrum(data: any, options: object)
Parameters
data (any = defaultData)
options (object = {})
Instance Members
peaks
clearCache()
maxY(options)
getSelectedPeaksWithCharge(selectedPeaks, options)
getChargeClusters(options)
getFragmentPeaksFct(mf, options)
getMassRemainderFct(mass, options)

getChargeClusters

Group the peaks into isotopologue clusters and give a charge to each cluster.

The charge of a single peak can not be evaluated: an isotopologue in the middle of an envelope looks the same whatever the charge, and the last one of an envelope has nothing after it. What carries the charge is the series: a run of peaks separated by NEUTRON_MASS / charge. So the series are searched first, and the charge of a series is given to all the peaks it holds.

A series of charge 1 is always a subseries of a series of charge 2, which is one of a series of charge 4: the clusters are therefore assigned from the one explaining the most intensity to the one explaining the least, and a peak only takes the charge of the first cluster that claims it.

getChargeClusters(peaks: Array<{x: number, y: number}>, options: object): Array<{charge: number, peaks: Array}>
Parameters
peaks (Array<{x: number, y: number}>) sorted by mass
options (object = {})
Name Description
options.minCharge number (default 1)
options.maxCharge number (default 10)
options.precision number (default 20) tolerance on the position of an isotopologue, in ppm. It is never allowed to reach half of the distance between two isotopologues, otherwise a series could jump from one to another.
options.minLength number (default 3) two peaks that happen to be at the right distance are common, three in a row much less
Returns
Array<{charge: number, peaks: Array}>: the clusters, from the one holding the most intensity to the one holding the least

buildClusters

The clusters as the two functions above need them: the position of the peaks rather than the peaks, and the intensity they hold to be able to sort them.

buildClusters(peaks: Array<{x: number, y: number}>, options: object): Array<{charge: number, indexes: Array<number>, intensity: number}>
Parameters
peaks (Array<{x: number, y: number}>)
options (object = {})
Returns
Array<{charge: number, indexes: Array<number>, intensity: number}>:

getPeaksWithClusterCharge

Give to each peak the charge of the cluster that explains it.

getPeaksWithClusterCharge(peaks: Array<{x: number, y: number}>, options: object): Array
Parameters
peaks (Array<{x: number, y: number}>) sorted by mass
options (object = {}) same as getChargeClusters
Returns
Array: copy of the peaks, with a charge when one was found

isOnPosition

Is the peak at index where the next isotopologue is expected?

The isotopologues of the charges z and z + 1 are only spacing / (z + 1) apart, and that distance shrinks fast: 0.5 Da between the charges 1 and 2, but 0.024 Da between 6 and 7. A tolerance that reaches it would let the same peaks be read with either charge, so it is capped well under.

isOnPosition(masses: Float64Array, index: number, expected: number, spacing: number, charge: number, precision: number): boolean
Parameters
masses (Float64Array)
index (number)
expected (number)
spacing (number)
charge (number)
precision (number) in ppm
Returns
boolean:

getFragmentPeaks

Filter the array of peaks

getFragmentPeaks(peaks: array, mf: string, options: object): array
Parameters
peaks (array) array of all the peaks
mf (string) Molecular formula of the parent molecule
options (object = {})
Name Description
options.from number? min X value of the window to consider
options.to number? max X value of the window to consider
options.threshold number (default 0.01) minimal intensity compare to base peak
options.limit number (default undefined) maximal number of peaks (based on intensity)
options.ionizations string?
options.precision number?
Returns
array: copy of peaks with 'close' annotation

getMassRemainder

Remove an integer number of time the specifiedd monoisotopic mass. Mass remainder analysis (MARA): https://doi.org/10.1021/acs.analchem.7b04730

getMassRemainder(spectrum: object, mass: number, options: object)
Parameters
spectrum (object)
mass (number)
options (object = {})
Name Description
options.delta number (default 0.001)

getPeakChargeBySimilarity

Evaluate the charge of the peak observed at a mass.

The charge is the one of the isotopologue cluster the peak belongs to, see getChargeClusters. A peak on its own shows no charge: what shows it is the series of peaks around it, separated by one dalton over the charge.

getPeakChargeBySimilarity(spectrum: any, targetMass: number, options: object): (number | undefined)
Parameters
spectrum (any)
targetMass (number)
options (object = {})
Name Description
options.minCharge number (default 1)
options.maxCharge number (default 10)
options.precision number (default 20) tolerance on the position of an isotopologue, in ppm
options.minLength number (default 3) shortest series that shows a charge
options.minSignalToNoise number (default 10) a peak under median plus minSignalToNoise times the standard deviation of the noise takes no part in the series: the position of a maximum of the noise is random and would give a charge to what is only noise. Only for a continuous spectrum, a list of centroids does not describe its noise anymore.
Returns
(number | undefined): the charge, or undefined when no series of peaks shows one at that mass

getMinIntensity

Intensity under which a peak is too close to the noise to say anything about a charge. The peak picking already removes what is under median + 3 sd, but a gaussian noise still leaves some of its maxima over it.

getMinIntensity(spectrum: any, options: object): number
Parameters
spectrum (any)
options (object = {})
Name Description
options.minSignalToNoise number (default 10)
Returns
number:

getPeaksWithCharge

Evaluate the charge of a selection of peaks.

The charge comes from the isotopologue clusters of allPeaks: a peak takes the charge of the series it belongs to. Evaluating a peak on its own can not work, because an isotopologue in the middle of an envelope looks the same whatever the charge and the last one of an envelope has nothing after it.

A peak that belongs to no series gets no charge at all.

getPeaksWithCharge(selectedPeaks: Array, allPeaks: Array, options: object): Array
Parameters
selectedPeaks (Array) peaks to evaluate
allPeaks (Array) all the peaks of the spectrum, sorted by mass
options (object = {})
Name Description
options.min number (default 1) lowest charge to consider
options.max number (default 10) highest charge to consider
options.precision number (default 20) tolerance on the position of an isotopologue, in ppm
options.minLength number (default 3) shortest series that shows a charge
options.minIntensity number (default 0) peaks under it are noise and take no part in the series
Returns
Array: copy of selectedPeaks , with a charge when one was found

getChargeAtMass

Charge of the clustered peak lying at a mass, if there is one there.

getChargeAtMass(clustered: Array, masses: any, targetMass: number, precision: number): (number | undefined)
Parameters
clustered (Array) peaks carrying their charge, sorted by mass
masses (any)
targetMass (number)
precision (number) in ppm
Returns
(number | undefined):

isContinuous

When a spectrum is continous ?

  • has more than 100 points
  • deltaX change can not be more than a factor 2
  • deltaX may not be larger than what maxDeltaX allows at that mass
  • if y is zero it does not count
isContinuous(spectrum: object, options: object)
Parameters
spectrum (object)
options (object = {})
Name Description
options.minLength number (default 100)
options.relativeHeightThreshold number (default 0.001) // Under this value the
options.maxDeltaRatio number (default 3)
options.maxDeltaX function? function called with the mass that returns the largest step a profile spectrum may have there. Defaults to defaultMaxDeltaX .

defaultMaxDeltaX

Largest step a profile spectrum may have around a mass.

A time of flight is sampled evenly in time and an orbitrap evenly in frequency, so in both the m/z step grows with the m/z: a MALDI-TOF is sampled every 0.19 Da around m/z 1000 and every 0.47 Da around m/z 6000, and is still a profile spectrum. The step is therefore allowed to grow with the mass, between two bounds:

  • never under 0.1 Da, so that a spectrum of small molecules keeps the step it always had
  • never over 0.6 Da, because the isotopologues of a singly charged ion are one dalton apart: over that a profile could not describe them, and a list of centroids would pass for one whatever its mass
defaultMaxDeltaX(mass: number): number
Parameters
mass (number)
Returns
number:

peakPicking

Filter the array of peaks

peakPicking(spectrum: any): array
Parameters
spectrum (any)
Returns
array:

getNoiseLevel

Intensity under which a maximum is considered to be noise.

We have to compute it ourselves: left alone, gsd only estimates a noise level when the x values are equally spaced within 5%, and falls back to 0 otherwise. A mass spectrum is sampled in time or in frequency, so over a wide m/z range the steps grow by far more than that and the noise would not be filtered.

getNoiseLevel(y: any, noiseFactor: number): (number | undefined)
Parameters
y (any)
noiseFactor (number = 3) 0 leaves the decision to gsd
Returns
(number | undefined):

getPeaks

Filter the array of peaks

getPeaks(peaks: array, options: object): array
Parameters
peaks (array) array of all the peaks
options (object = {})
Name Description
options.from number? min X value of the window to consider
options.to number? max X value of the window to consider
options.threshold number (default 0.01) minimal intensity compare to base peak
options.limit number (default undefined) maximal number of peaks (based on intensity)
options.sumValue number? // if sumValue is defined, maxValue is ignored
Returns
array: copy of peaks with 'close' annotation

getBestPeaks

Filter the array by taking the higher peaks and only keep one per slot. There are 2 different slots, the smallest one will have the extra annotation close to true

getBestPeaks(peaks: array, options: object): array
Parameters
peaks (array) array of all the peaks
options (object = {})
Name Description
options.from number? min X value of the window to consider
options.to number? max X value of the window to consider
options.minValue number (default Number.NEGATIVE_INFINITY) min Y value of the window to consider
options.maxValue number (default Number.POSITIVE_INFINITY) max Y value of the window to consider
options.searchMonoisotopicRatio number (default 0) search previous peaks with at least ratio height
options.limit number (default 20) max number of peaks
options.threshold number (default 0.01) minimal intensity compare to base peak
options.numberSlots number (default 10) define the number of slots and indirectly the slot width
options.numberCloseSlots number (default 50)
Returns
array: copy of peaks with 'close' annotation

constructor

Create a class that will be able to get the similarity between 2 spectra The similarity is based on 'cosine' similarity. The goal is 2 prepare 2 vectors on which the similarity is calculated. The vectors are created by taking the mass and the intensity of the peaks.

constructor(options: object)
Parameters
options (object = {})
Name Description
options.nbPeaks number? Before comparing spectra how many peaks should be kept
options.minNbCommonPeaks number? Minimum number of peaks in common to consider any similarity
options.minIntensity number? What is the minimal relative intensity to keep a peak
options.massPower number (default 3) High power will give more weight to the mass. If you would prefer to observe fragments you should use a number less than 1
options.intensityPower number (default 0.6) How important is the intensity. By default we don't give to much importance to it
options.selectedMasses Array<number>? List of allowed masses.
options.delta (number | Function) (default 0.1) Tolerance in Da (u) to consider 2 peaks as aligned. If a function is provided it will be called with the mass of the peak

getSimilarityToMasses

Get the similarity between a spectrum and a list of masses. The main issue is that we don't have the intensity of the peaks. So we will use the intensity of the closest peak.

getSimilarityToMasses(dataXY: any, masses: Array<number>)
Parameters
dataXY (any)
masses (Array<number>)

getSimilarity

getSimilarity(dataXY1: any, dataXY2: any)
Parameters
dataXY1 (any)
dataXY2 (any)

normalizeAndCacheData

normalizeAndCacheData(cache: WeakMap, dataXY: any, options: object)
Parameters
cache (WeakMap)
dataXY (any)
options (object = {})
Name Description
options.nbPeaks number?
options.minIntensity number?

returnSimilarity

returnSimilarity(aligned: any, options: object)
Parameters
aligned (any)
options (object = {})
Name Description
options.massPower number?
options.intensityPower number?
options.minNbCommonPeaks number?

cosineSimilarity

Returns the average of cosine distances between vectors a and b Copied from https://github.com/mljs/distance/blob/0b15acd6476413f4111cb4852ca1bec9edaa2805/src/similarities/cosine.ts

cosineSimilarity(a: any, b: any): number
Parameters
a (any) {import('cheminfo-types').NumberArray} - first vector
b (any) {import('cheminfo-types').NumberArray} - second vector
Returns
number: cosine similarity

getPeaksAnnotation

getPeaksAnnotation(bestPeaks: array, options: object): Promise
Parameters
bestPeaks (array)
options (object = {})
Name Description
options.numberDigits number (default 5)
options.numberMFs number (default 0)
options.showMF boolean (default false)
options.mfColors array (default {})
options.charge number (default 1)
options.shift number (default 0)
options.mfPrefs object?
options.displayCharge number (default true)
options.displayProperties number (default []) Array of properties name to display
Returns
Promise:

fromMonoisotopicMass

Generates a database 'monoisotopic' from a monoisotopic mass and various options

fromMonoisotopicMass(masses: (number | string | array), options: object): Promise
Parameters
masses ((number | string | array)) Monoisotopic mass
options (object = {})
Name Description
options.maxIterations number (default 10000000) Maximum number of iterations
options.onStep function? Callback to do after each step
options.allowNeutral boolean (default true)
options.uniqueMFs boolean (default true)
options.limit number (default 1000) Maximum number of results
options.ionizations string (default '') string containing a comma separated list of modifications
options.ranges string (default 'C0-100 H0-100 O0-100 N0-100') range of mfs to search
options.precision number (default 100) Allowed mass range based on precision
options.filter object (default {})
options.filter.minCharge number (default -Infinity) Minimal charge
options.filter.maxCharge number (default +Infinity) Maximal charge
options.filter.absoluteCharge boolean (default false) If true, the charge is absolute (so between 0 and +Infinity by default)
options.filter.unsaturation object (default {})
options.filter.unsaturation.min number (default -Infinity) Minimal unsaturation
options.filter.unsaturation.max number (default +Infinity) Maximal unsaturation
options.filter.unsaturation.onlyInteger boolean (default false) Integer unsaturation
options.filter.unsaturation.onlyNonInteger boolean (default false) Non integer unsaturation
options.filter.atoms object? object of atom:{min, max}
options.filter.callback function? a function to filter the MF
Returns
Promise: