peptide
Version:
96 lines • 4.09 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.generatePeptideFragments = generatePeptideFragments;
/**
* Generate peptide fragments from a molecular formula.
* @param {string} mf - The molecular formula to fragment.
* @param {object} [options] - Fragmentation options.
* @param {boolean} [options.a=false] - Generate a-type fragments.
* @param {boolean} [options.b] - Generate b-type fragments. Defaults to `true` if no options are specified, otherwise `false`.
* @param {boolean} [options.c=false] - Generate c-type fragments.
* @param {boolean} [options.x=false] - Generate x-type fragments.
* @param {boolean} [options.y] - Generate y-type fragments. Defaults to `true` if no options are specified, otherwise `false`.
* @param {boolean} [options.z=false] - Generate z-type fragments.
* @param {boolean} [options.i=false] - Generate internal fragments.
* @param {boolean} [options.ya=false] - Generate ya-type double fragmentation.
* @param {boolean} [options.yb=false] - Generate yb-type double fragmentation.
* @param {boolean} [options.yc=false] - Generate yc-type double fragmentation.
* @param {boolean} [options.zc=false] - Generate zc-type double fragmentation.
* @param {number} [options.maxInternal=Infinity] - Maximum number of residues for internal fragments.
* @param {number} [options.minInternal=0] - Minimum number of residues for internal fragments.
* @returns {string[]} Array of fragment molecular formulas.
*/
function generatePeptideFragments(mf, options) {
const isDefaultCall = options === undefined;
if (isDefaultCall) {
options = {};
}
const { a = false, b = isDefaultCall, c = false, x = false, y = isDefaultCall, z = false, i: internal = false, ya = false, yb = false, yc = false, zc = false, maxInternal = Number.MAX_VALUE, minInternal = 0, } = options;
let mfs = [];
// need to allow 0-9 to deal with neutral loss
let mfparts = mf
.replaceAll(/([\d)a-z])([A-Z][a-z](?=[a-z]))/g, '$1 $2')
.split(/ /);
let nTerm = '';
let cTerm = '';
if (mfparts[0].startsWith('(')) {
nTerm += mfparts[0];
mfparts = mfparts.splice(1);
}
if (mfparts.at(-1).includes('(')) {
cTerm += mfparts.at(-1).replace(/^[^()]*/, '');
mfparts[mfparts.length - 1] = mfparts.at(-1).replace(/\(.*/, '');
}
for (let i = 1; i < mfparts.length; i++) {
nTerm += mfparts[i - 1];
cTerm = mfparts[mfparts.length - i] + cTerm;
addNTerm(mfs, nTerm, i, a, b, c);
addCTerm(mfs, cTerm, i, x, y, z);
if (internal)
mfs.push(`${mfparts[i]}HC-1O-1(+1)$i:${mfparts[i]}`);
if (ya || yb || yc || zc) {
// we have double fragmentations
for (let j = i + 1; j < Math.min(mfparts.length, maxInternal + i + 1); j++) {
let iTerm = '';
if (j - i >= minInternal) {
for (let k = i; k < j; k++) {
iTerm += mfparts[k];
}
addITerm(mfs, iTerm, mfparts.length - i, j, ya, yb, yc, zc);
}
}
}
}
// todo does this make sense ??? I think we should remote those 3 lines
if (mfs.length === 0) {
mfs = mfs.concat([mf]);
}
return mfs;
}
function addNTerm(mfs, nTerm, i, a, b, c) {
if (a)
mfs.push(`${nTerm}C-1O-1(+1)$a${i}`);
if (b)
mfs.push(`${nTerm}(+1)$b${i}`);
if (c)
mfs.push(`${nTerm}NH3(+1)$c${i}`);
}
function addITerm(mfs, iTerm, i, j, ya, yb, yc, zc) {
if (ya)
mfs.push(`H${iTerm}C-1O-1(+1)$a${j}y${i}`);
if (yb)
mfs.push(`H${iTerm}(+1)$b${j}y${i}`);
if (yc)
mfs.push(`H${iTerm}NH3(+1)$c${j}y${i}`);
if (zc)
mfs.push(`N-1${iTerm}NH3(+1)$c${j}z${i}`);
}
function addCTerm(mfs, cTerm, i, x, y, z) {
if (x)
mfs.push(`CO(+1)${cTerm}$x${i}`);
if (y)
mfs.push(`H2(+1)${cTerm}$y${i}`);
if (z)
mfs.push(`N-1H-1(+1)${cTerm}$z${i}`);
}
//# sourceMappingURL=generatePeptideFragments.js.map