{"version":3,"file":"mgf-parser.umd.min.js","sources":["../node_modules/is-any-array/lib/index.js","../node_modules/ml-spectra-processing/lib/x/xCheck.js","../node_modules/ml-spectra-processing/lib/x/xFindClosestIndex.js","../node_modules/ml-spectra-processing/lib/x/xGetFromToIndex.js","../node_modules/ml-spectra-processing/lib/utils/isLittleEndian.js","../node_modules/ml-spectra-processing/lib/x/utils/radixSortOrder.js","../node_modules/ml-spectra-processing/lib/x/xNormed.js","../node_modules/ml-spectra-processing/lib/x/getOutputArray.js","../node_modules/ml-spectra-processing/lib/x/xMaxValue.js","../node_modules/ml-spectra-processing/lib/x/xSum.js","../node_modules/ml-spectra-processing/lib/xy/xySortX.js","../node_modules/ml-spectra-processing/lib/x/xIsMonotonic.js","../node_modules/ml-spectra-processing/lib/x/xGetSortOrder.js","../node_modules/ml-spectra-processing/lib/xy/xyUniqueX.js","../node_modules/ml-spectra-processing/lib/xy/xyCheck.js","../lib/index.js"],"sourcesContent":["// eslint-disable-next-line @typescript-eslint/unbound-method\nconst toString = Object.prototype.toString;\n/**\n * Checks if an object is an instance of an Array (array or typed array, except those that contain bigint values).\n * @param value - Object to check.\n * @returns True if the object is an array or a typed array.\n */\nexport function isAnyArray(value) {\n    const tag = toString.call(value);\n    return tag.endsWith('Array]') && !tag.includes('Big');\n}\n//# sourceMappingURL=index.js.map","import { isAnyArray } from 'is-any-array';\n/**\n * Checks if the input is a non-empty array of numbers.\n * Only checks the first element.\n * @param input - array to check.\n * @param options - additional checks.\n */\nexport function xCheck(input, options = {}) {\n    const { minLength = 1 } = options;\n    if (!isAnyArray(input)) {\n        throw new TypeError('input must be an array');\n    }\n    if (input.length === 0) {\n        throw new TypeError('input must not be empty');\n    }\n    if (typeof input[0] !== 'number') {\n        throw new TypeError('input must contain numbers');\n    }\n    if (input.length < minLength) {\n        throw new Error(`input must have a length of at least ${minLength}`);\n    }\n}\n//# sourceMappingURL=xCheck.js.map","/**\n * Returns the closest index of a `target`\n * @param array - array of numbers.\n * @param target - target value.\n * @param options - options.\n * @returns closest index.\n */\nexport function xFindClosestIndex(array, target, options = {}) {\n    const { sorted = true } = options;\n    if (sorted) {\n        let low = 0;\n        let high = array.length - 1;\n        let middle = 0;\n        while (high - low > 1) {\n            middle = low + ((high - low) >> 1);\n            if (array[middle] < target) {\n                low = middle;\n            }\n            else if (array[middle] > target) {\n                high = middle;\n            }\n            else {\n                return middle;\n            }\n        }\n        if (low < array.length - 1) {\n            if (Math.abs(target - array[low]) < Math.abs(array[low + 1] - target)) {\n                return low;\n            }\n            else {\n                return low + 1;\n            }\n        }\n        else {\n            return low;\n        }\n    }\n    else {\n        let index = 0;\n        let diff = Number.POSITIVE_INFINITY;\n        for (let i = 0; i < array.length; i++) {\n            const currentDiff = Math.abs(array[i] - target);\n            if (currentDiff < diff) {\n                diff = currentDiff;\n                index = i;\n            }\n        }\n        return index;\n    }\n}\n//# sourceMappingURL=xFindClosestIndex.js.map","import { xFindClosestIndex } from \"./xFindClosestIndex.js\";\n/**\n * Returns an object with {fromIndex, toIndex} for a specific from / to\n * @param x - array of numbers\n * @param options - options.\n */\nexport function xGetFromToIndex(x, options = {}) {\n    let { fromIndex, toIndex } = options;\n    const { from, to } = options;\n    if (fromIndex === undefined) {\n        if (from !== undefined) {\n            fromIndex = xFindClosestIndex(x, from);\n        }\n        else {\n            fromIndex = 0;\n        }\n    }\n    if (toIndex === undefined) {\n        if (to !== undefined) {\n            toIndex = xFindClosestIndex(x, to);\n        }\n        else {\n            toIndex = x.length - 1;\n        }\n    }\n    if (fromIndex < 0)\n        fromIndex = 0;\n    if (toIndex < 0)\n        toIndex = 0;\n    if (fromIndex >= x.length)\n        fromIndex = x.length - 1;\n    if (toIndex >= x.length)\n        toIndex = x.length - 1;\n    if (fromIndex > toIndex)\n        [fromIndex, toIndex] = [toIndex, fromIndex];\n    return { fromIndex, toIndex };\n}\n//# sourceMappingURL=xGetFromToIndex.js.map","const LITTLE_ENDIAN = new Uint8Array(new Uint16Array([1]).buffer)[0] === 1;\n/**\n * Check whether the host stores multi-byte values least significant byte first.\n * Needed whenever a typed array is reinterpreted through another view, because\n * the position of the words of a value then depends on the platform.\n * @returns true on a little-endian host.\n */\nexport function isLittleEndian() {\n    return LITTLE_ENDIAN;\n}\n//# sourceMappingURL=isLittleEndian.js.map","import { isLittleEndian } from \"../../utils/isLittleEndian.js\";\n// Internal helpers: not re-exported from `x/index.ts`, so they stay out of the public API.\n// The counting pass costs O(radix) whatever the length, so the digit stays narrow until the\n// array is long enough to amortize a wide one.\nconst SMALL_DIGIT_BITS = 8;\nconst LARGE_DIGIT_BITS = 16;\nconst LARGE_ARRAY_LENGTH = 1 << LARGE_DIGIT_BITS;\n/**\n * Length from which ordering through the radix beats a comparator, for a caller that has to\n * build the keys and read the values back through the order. The measured crossover is around\n * 150 values on both V8 and JavaScriptCore, whether the values come from a typed array, a\n * plain array or the x of an array of points.\n */\nexport const RADIX_ORDER_MIN_LENGTH = 1 << SMALL_DIGIT_BITS;\n/**\n * Orders the values by their full 64 bits, as an LSD radix sort.\n * @param array - the values to order.\n * @param descending - order from the largest to the smallest.\n * @returns the indices of the values, in order.\n */\nexport function radixSortOrderExact(array, descending) {\n    const values = ensureFloat64(array);\n    const length = values.length;\n    let order = new Uint32Array(length);\n    if (length < 2)\n        return order;\n    const digitBits = getDigitBits(length);\n    const radix = 1 << digitBits;\n    const digitMask = radix - 1;\n    const words = new Uint32Array(values.buffer, values.byteOffset, length * 2);\n    const flip = descending ? 0xffffffff : 0;\n    const highWord = isLittleEndian() ? 1 : 0;\n    const lowWord = 1 - highWord;\n    let keysLow = new Uint32Array(length);\n    let keysHigh = new Uint32Array(length);\n    for (let i = 0; i < length; i++) {\n        const high = words[i * 2 + highWord];\n        const low = words[i * 2 + lowWord];\n        // Monotonic unsigned key of the double: a negative flips every bit, a positive only the\n        // sign bit. Complementing that key reverses the order.\n        if ((high & 0x80000000) === 0) {\n            keysHigh[i] = high ^ 0x80000000 ^ flip;\n            keysLow[i] = low ^ flip;\n        }\n        else {\n            keysHigh[i] = ~high ^ flip;\n            keysLow[i] = ~low ^ flip;\n        }\n        order[i] = i;\n    }\n    let nextOrder = new Uint32Array(length);\n    let nextLow = new Uint32Array(length);\n    let nextHigh = new Uint32Array(length);\n    const counts = new Uint32Array(radix);\n    for (let shift = 0; shift < 64; shift += digitBits) {\n        const onHigh = shift >= 32;\n        const wordShift = onHigh ? shift - 32 : shift;\n        const keys = onHigh ? keysHigh : keysLow;\n        counts.fill(0);\n        for (let i = 0; i < length; i++) {\n            counts[(keys[i] >>> wordShift) & digitMask]++;\n        }\n        // A digit shared by every value would make this pass the identity.\n        if (counts[(keys[0] >>> wordShift) & digitMask] === length)\n            continue;\n        cumulate(counts);\n        for (let i = 0; i < length; i++) {\n            const low = keysLow[i];\n            const high = keysHigh[i];\n            const at = counts[((onHigh ? high : low) >>> wordShift) & digitMask]++;\n            nextOrder[at] = order[i];\n            nextLow[at] = low;\n            nextHigh[at] = high;\n        }\n        // A destructuring swap makes JavaScriptCore give up the typed array specialization of\n        // these variables, which costs 8x on the whole sort.\n        let swap = order;\n        order = nextOrder;\n        nextOrder = swap;\n        swap = keysLow;\n        keysLow = nextLow;\n        nextLow = swap;\n        swap = keysHigh;\n        keysHigh = nextHigh;\n        nextHigh = swap;\n    }\n    return order;\n}\n/**\n * Orders the values by the high word of each double, as an LSD radix sort. Values differing by\n * less than their 2^-20 relative resolution share a key and keep their input order.\n * @param array - the values to order.\n * @param descending - order from the largest to the smallest.\n * @returns the indices of the values, in order.\n */\nexport function radixSortOrderApproximate(array, descending) {\n    const values = ensureFloat64(array);\n    const length = values.length;\n    let order = new Uint32Array(length);\n    if (length < 2)\n        return order;\n    const digitBits = getDigitBits(length);\n    const radix = 1 << digitBits;\n    const digitMask = radix - 1;\n    const words = new Uint32Array(values.buffer, values.byteOffset, length * 2);\n    const flip = descending ? 0xffffffff : 0;\n    const highWord = isLittleEndian() ? 1 : 0;\n    let keys = new Uint32Array(length);\n    for (let i = 0; i < length; i++) {\n        const high = words[i * 2 + highWord];\n        keys[i] = ((high & 0x80000000) === 0 ? high ^ 0x80000000 : ~high) ^ flip;\n        order[i] = i;\n    }\n    let nextOrder = new Uint32Array(length);\n    let nextKeys = new Uint32Array(length);\n    const counts = new Uint32Array(radix);\n    for (let shift = 0; shift < 32; shift += digitBits) {\n        counts.fill(0);\n        for (let i = 0; i < length; i++) {\n            counts[(keys[i] >>> shift) & digitMask]++;\n        }\n        if (counts[(keys[0] >>> shift) & digitMask] === length)\n            continue;\n        cumulate(counts);\n        for (let i = 0; i < length; i++) {\n            const key = keys[i];\n            const at = counts[(key >>> shift) & digitMask]++;\n            nextOrder[at] = order[i];\n            nextKeys[at] = key;\n        }\n        // See radixSortOrderExact: a destructuring swap is 8x slower on JavaScriptCore.\n        let swap = order;\n        order = nextOrder;\n        nextOrder = swap;\n        swap = keys;\n        keys = nextKeys;\n        nextKeys = swap;\n    }\n    return order;\n}\n/**\n * Turns the counts of each digit into the position its first entry goes to.\n * @param counts - counts per digit, replaced in place by the start offsets.\n */\nfunction cumulate(counts) {\n    let start = 0;\n    for (let i = 0; i < counts.length; i++) {\n        const count = counts[i];\n        counts[i] = start;\n        start += count;\n    }\n}\n/**\n * Picks the digit width, keeping the radix no wider than the array it scans.\n * @param length - number of values to order.\n * @returns the number of bits of one digit.\n */\nfunction getDigitBits(length) {\n    return length >= LARGE_ARRAY_LENGTH ? LARGE_DIGIT_BITS : SMALL_DIGIT_BITS;\n}\n/**\n * Returns the values as a Float64Array, without copying one that already is.\n * @param array - values.\n * @returns the values, readable as doubles.\n */\nfunction ensureFloat64(array) {\n    return array instanceof Float64Array ? array : Float64Array.from(array);\n}\n//# sourceMappingURL=radixSortOrder.js.map","import { getOutputArray } from \"./getOutputArray.js\";\nimport { xCheck } from \"./xCheck.js\";\nimport { xMaxValue } from \"./xMaxValue.js\";\nimport { xSum } from \"./xSum.js\";\n/**\n * Divides the data with either the sum, the absolute sum or the maximum of the data\n * @param input - array containing values.\n * @param options - options.\n * @returns normalized data.\n */\nexport function xNormed(input, options = {}) {\n    const { algorithm = 'absolute', value = 1 } = options;\n    xCheck(input);\n    const output = getOutputArray(options.output, input.length);\n    if (input.length === 0) {\n        throw new Error('input must not be empty');\n    }\n    switch (algorithm) {\n        case 'absolute': {\n            const absoluteSumValue = absoluteSum(input) / value;\n            if (absoluteSumValue === 0) {\n                throw new Error('trying to divide by 0');\n            }\n            for (let i = 0; i < input.length; i++) {\n                output[i] = input[i] / absoluteSumValue;\n            }\n            return output;\n        }\n        case 'max': {\n            const currentMaxValue = xMaxValue(input);\n            if (currentMaxValue === 0) {\n                throw new Error('trying to divide by 0');\n            }\n            const factor = value / currentMaxValue;\n            for (let i = 0; i < input.length; i++) {\n                output[i] = input[i] * factor;\n            }\n            return output;\n        }\n        case 'sum': {\n            const sumFactor = xSum(input) / value;\n            if (sumFactor === 0) {\n                throw new Error('trying to divide by 0');\n            }\n            for (let i = 0; i < input.length; i++) {\n                output[i] = input[i] / sumFactor;\n            }\n            return output;\n        }\n        default:\n            throw new Error(`unknown algorithm: ${String(algorithm)}`);\n    }\n}\nfunction absoluteSum(input) {\n    let sumValue = 0;\n    for (let i = 0; i < input.length; i++) {\n        sumValue += Math.abs(input[i]);\n    }\n    return sumValue;\n}\n//# sourceMappingURL=xNormed.js.map","import { isAnyArray } from 'is-any-array';\n/**\n * This function\n * @param output - undefined or a new array\n * @param length - length of the output array\n * @returns\n */\nexport function getOutputArray(output, length) {\n    if (output !== undefined) {\n        if (!isAnyArray(output)) {\n            throw new TypeError('output option must be an array if specified');\n        }\n        if (output.length !== length) {\n            throw new TypeError('the output array does not have the correct length');\n        }\n        return output;\n    }\n    else {\n        return new Float64Array(length);\n    }\n}\n//# sourceMappingURL=getOutputArray.js.map","import { xCheck } from \"./xCheck.js\";\nimport { xGetFromToIndex } from \"./xGetFromToIndex.js\";\n/**\n * Computes the maximal value of an array of values\n * @param array - array of numbers\n * @param options - options\n */\nexport function xMaxValue(array, options = {}) {\n    xCheck(array);\n    const { fromIndex, toIndex } = xGetFromToIndex(array, options);\n    let maxValue = array[fromIndex];\n    for (let i = fromIndex + 1; i <= toIndex; i++) {\n        if (array[i] > maxValue) {\n            maxValue = array[i];\n        }\n    }\n    return maxValue;\n}\n//# sourceMappingURL=xMaxValue.js.map","import { xCheck } from \"./xCheck.js\";\nimport { xGetFromToIndex } from \"./xGetFromToIndex.js\";\n/**\n * Calculate the sum of the values\n * @param array - object that contains property x (an ordered increasing array) and y (an array).\n * @param options - options.\n * @returns sum value on the specified range.\n */\nexport function xSum(array, options = {}) {\n    xCheck(array);\n    const { fromIndex, toIndex } = xGetFromToIndex(array, options);\n    let sumValue = array[fromIndex];\n    for (let i = fromIndex + 1; i <= toIndex; i++) {\n        sumValue += array[i];\n    }\n    return sumValue;\n}\n//# sourceMappingURL=xSum.js.map","import { xGetSortOrder, xIsMonotonic } from \"../x/index.js\";\nimport { RADIX_ORDER_MIN_LENGTH } from \"../x/utils/radixSortOrder.js\";\n/**\n * This function performs a quick sort of the x array while transforming the y array to preserve the coordinates.\n * @param data - object that contains property x (Array) and y (Array).\n * @returns the points, ascending by x.\n */\nexport function xySortX(data) {\n    const { x, y } = data;\n    if (xIsMonotonic(x) && x.length > 1) {\n        const floatX = Float64Array.from(x);\n        const floatY = Float64Array.from(y);\n        if (floatX.at(-1) < floatX[0]) {\n            floatX.reverse();\n            floatY.reverse();\n        }\n        return {\n            x: floatX,\n            y: floatY,\n        };\n    }\n    const response = {\n        x: new Float64Array(x.length),\n        y: new Float64Array(y.length),\n    };\n    if (x.length >= RADIX_ORDER_MIN_LENGTH) {\n        const order = xGetSortOrder(x);\n        for (let i = 0; i < order.length; i++) {\n            const at = order[i];\n            response.x[i] = x[at];\n            response.y[i] = y[at];\n        }\n        return response;\n    }\n    const xyObject = Array.from(x, (val, index) => ({\n        x: val,\n        y: y[index],\n    }));\n    xyObject.sort((a, b) => a.x - b.x);\n    for (let i = 0; i < x.length; i++) {\n        response.x[i] = xyObject[i].x;\n        response.y[i] = xyObject[i].y;\n    }\n    return response;\n}\n//# sourceMappingURL=xySortX.js.map","/**\n * Returns true if x is monotonic.\n * @param array - array of numbers.\n * @returns 1 if monotonic increasing, -1 if monotonic decreasing, 0 if not monotonic.\n */\nexport function xIsMonotonic(array) {\n    if (array.length < 2) {\n        return 1;\n    }\n    if (array[0] === array[1]) {\n        // maybe a constant series\n        for (let i = 1; i < array.length - 1; i++) {\n            if (array[i] !== array[i + 1])\n                return 0;\n        }\n        return 1;\n    }\n    if (array[0] < array.at(-1)) {\n        for (let i = 0; i < array.length - 1; i++) {\n            if (array[i] >= array[i + 1])\n                return 0;\n        }\n        return 1;\n    }\n    else {\n        for (let i = 0; i < array.length - 1; i++) {\n            if (array[i] <= array[i + 1])\n                return 0;\n        }\n        return -1;\n    }\n}\n//# sourceMappingURL=xIsMonotonic.js.map","import { radixSortOrderExact } from \"./utils/radixSortOrder.js\";\n/**\n * Returns the indices that order the values, without moving them.\n * The sort is a radix sort over the full 64 bits of each double: it costs a fixed number of\n * linear passes instead of the n log n comparisons of `Array.prototype.sort`, and orders\n * exactly, NaN, infinities, subnormals and the two zeros included.\n * The sort is stable, so equal values keep their input order.\n * @param array - values to order.\n * @param options - options.\n * @returns the indices of the values, in order.\n */\nexport function xGetSortOrder(array, options = {}) {\n    const { descending = false } = options;\n    return radixSortOrderExact(array, descending);\n}\n//# sourceMappingURL=xGetSortOrder.js.map","import { xyCheck } from \"./xyCheck.js\";\nimport { xySortX } from \"./xySortX.js\";\n/**\n * Ensure x values are unique\n * @param data - object that contains property x (Array) and y (Array).\n * @param options - object containing a property algorithm (can be 'sum' or 'average', the latter being the default value), and a property isSorted (boolean indicating if the x-array is sorted).\n */\nexport function xyUniqueX(data, options = {}) {\n    xyCheck(data);\n    if (data.x.length === 0) {\n        return { x: [], y: [] };\n    }\n    const { algorithm = 'average', isSorted = true } = options;\n    if (!isSorted) {\n        data = xySortX(data);\n    }\n    switch (algorithm) {\n        case 'average':\n            return average(data);\n        case 'sum':\n            return sum(data);\n        default:\n            throw new Error(`unknown algorithm: ${String(algorithm)}`);\n    }\n}\n/**\n * Averages duplicate x values by averaging their y values.\n * @param data - input.\n * @returns result.\n */\nfunction average(data) {\n    const x = [];\n    const y = [];\n    let cumulativeY = data.y[0];\n    let divider = 1;\n    for (let i = 1; i < data.x.length; i++) {\n        if (!(data.x[i] === data.x[i - 1])) {\n            x.push(data.x[i - 1]);\n            y.push(cumulativeY / divider);\n            cumulativeY = 0;\n            divider = 0;\n        }\n        cumulativeY += data.y[i];\n        divider++;\n    }\n    x.push(data.x.at(-1));\n    y.push(cumulativeY / divider);\n    return { x, y };\n}\n/**\n * Merges duplicate x values by summing their y values.\n * @param data - input.\n * @returns result.\n */\nfunction sum(data) {\n    const x = [];\n    const y = [];\n    let cumulativeY = data.y[0];\n    for (let i = 1; i < data.x.length; i++) {\n        if (!(data.x[i] === data.x[i - 1])) {\n            x.push(data.x[i - 1]);\n            y.push(cumulativeY);\n            cumulativeY = 0;\n        }\n        cumulativeY += data.y[i];\n    }\n    x.push(data.x.at(-1));\n    y.push(cumulativeY);\n    return { x, y };\n}\n//# sourceMappingURL=xyUniqueX.js.map","import { isAnyArray } from 'is-any-array';\n/**\n * Verify that `data` is an object of x,y arrays.\n * Throws an error if it's not.\n * @param data - data to check.\n * @param options - options.\n * @param options.minLength - minimum required length.\n */\nexport function xyCheck(data, options = {}) {\n    const { minLength } = options;\n    if (data === null ||\n        typeof data !== 'object' ||\n        // @ts-expect-error Typechecking\n        !isAnyArray(data.x) ||\n        // @ts-expect-error Typechecking\n        !isAnyArray(data.y)) {\n        throw new Error('data must be an object of x and y arrays');\n    }\n    // @ts-expect-error Typechecking\n    if (data.x.length !== data.y.length) {\n        throw new Error('the x and y arrays must have the same length');\n    }\n    // @ts-expect-error Typechecking\n    if (minLength && data.x.length < minLength) {\n        throw new Error(`data.x must have a length of at least ${minLength}`);\n    }\n}\n//# sourceMappingURL=xyCheck.js.map","import { xNormed, xySortX, xyUniqueX } from 'ml-spectra-processing';\nconst BEGIN_REGEXP = /^BEGIN\\b\\s*(?<kind>.*)$/;\nconst END_REGEXP = /^END\\b/;\nconst COMMENT_REGEXP = /^[!#;/]/;\nconst PEAK_SEPARATOR_REGEXP = /[ \\t,;]+/;\n/**\n * Parses MGF files into a JSON. The spectrum can be delimited by ' ', '\\t', ',' or ';'.\n * Comment lines (starting with '#', ';', '!' or '/'), blank lines and the optional\n * third column of a peak line (the fragment charge) are ignored.\n * @param rawData - Input data (MGF).\n * @param options - Parsing options.\n * @returns Parsed data entries.\n */\nexport function parse(rawData, options = {}) {\n    const { recordTypes = '', uniqueX = false, normedY = false, maxY } = options;\n    if (normedY && maxY !== undefined) {\n        throw new Error('Option maxY must be undefined if normedY is true');\n    }\n    const shouldSortX = uniqueX || (options.sortX ?? false);\n    const recordTypesRegExp = new RegExp(recordTypes);\n    const lines = rawData.split(/\\r?\\n/);\n    const results = [];\n    const globalMeta = {};\n    let entry;\n    let peaks = { x: [], y: [] };\n    let shouldSkip = false;\n    for (let i = 0; i < lines.length; i++) {\n        const line = lines[i]?.trim();\n        if (!line || COMMENT_REGEXP.test(line))\n            continue;\n        const begin = BEGIN_REGEXP.exec(line);\n        if (begin) {\n            const kind = begin.groups?.kind ?? '';\n            shouldSkip = !recordTypesRegExp.test(kind);\n            entry = { data: { x: [], y: [] }, meta: { ...globalMeta }, kind };\n            peaks = { x: [], y: [] };\n            continue;\n        }\n        if (END_REGEXP.test(line)) {\n            if (entry && !shouldSkip) {\n                entry.data = treatSpectrum(peaks, {\n                    shouldSortX,\n                    uniqueX,\n                    normedY,\n                    maxY,\n                });\n                results.push(entry);\n            }\n            entry = undefined;\n            shouldSkip = false;\n            continue;\n        }\n        if (shouldSkip)\n            continue;\n        const equalPosition = line.indexOf('=');\n        if (equalPosition !== -1) {\n            const key = line.slice(0, equalPosition);\n            const value = line.slice(equalPosition + 1);\n            if (entry) {\n                entry.meta[key] = value;\n            }\n            else {\n                globalMeta[key] = value;\n            }\n            continue;\n        }\n        const fields = line.split(PEAK_SEPARATOR_REGEXP);\n        const x = Number(fields[0]);\n        const y = Number(fields[1]);\n        if (Number.isNaN(x) || Number.isNaN(y)) {\n            throw new Error(`Could not parse line number ${i + 1}`);\n        }\n        if (!entry) {\n            throw new Error(`Found fragment ion data outside of a BEGIN/END block on line number ${i + 1}`);\n        }\n        peaks.x.push(x);\n        peaks.y.push(y);\n    }\n    return results;\n}\nfunction treatSpectrum(peaks, options) {\n    const { shouldSortX, uniqueX, normedY, maxY } = options;\n    let spectrum = shouldSortX ? xySortX(peaks) : peaks;\n    if (uniqueX) {\n        spectrum = xyUniqueX(spectrum, { algorithm: 'sum' });\n    }\n    if (normedY) {\n        return { x: spectrum.x, y: xNormed(spectrum.y) };\n    }\n    if (maxY !== undefined) {\n        return {\n            x: spectrum.x,\n            y: xNormed(spectrum.y, { algorithm: 'max', value: maxY }),\n        };\n    }\n    return spectrum;\n}\n//# sourceMappingURL=index.js.map"],"names":["toString","Object","prototype","isAnyArray","value","tag","call","endsWith","includes","xCheck","input","options","minLength","TypeError","length","Error","xFindClosestIndex","array","target","sorted","low","high","middle","Math","abs","index","diff","Number","POSITIVE_INFINITY","i","currentDiff","xGetFromToIndex","x","fromIndex","toIndex","from","to","undefined","LITTLE_ENDIAN","Uint8Array","Uint16Array","buffer","radixSortOrderExact","descending","values","Float64Array","ensureFloat64","order","Uint32Array","digitBits","getDigitBits","radix","digitMask","words","byteOffset","flip","highWord","lowWord","keysLow","keysHigh","nextOrder","nextLow","nextHigh","counts","shift","onHigh","wordShift","keys","fill","cumulate","at","swap","start","count","xNormed","algorithm","output","getOutputArray","absoluteSumValue","sumValue","absoluteSum","currentMaxValue","maxValue","xMaxValue","factor","sumFactor","xSum","String","xySortX","data","y","xIsMonotonic","floatX","floatY","reverse","response","xGetSortOrder","xyObject","Array","val","sort","a","b","xyUniqueX","xyCheck","isSorted","cumulativeY","divider","push","average","sum","BEGIN_REGEXP","END_REGEXP","COMMENT_REGEXP","PEAK_SEPARATOR_REGEXP","treatSpectrum","peaks","shouldSortX","uniqueX","normedY","maxY","spectrum","rawData","recordTypes","sortX","recordTypesRegExp","RegExp","lines","split","results","globalMeta","entry","shouldSkip","line","trim","test","begin","exec","kind","groups","meta","equalPosition","indexOf","key","slice","fields","isNaN"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]}