UNPKG

sequaljs

Version:

JavaScript/TypeScript library for parsing and manipulating ProForma peptide sequence notation

289 lines (288 loc) 16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // src/__tests__/proforma.test.ts const proforma_1 = require("../proforma"); describe('ProFormaParser', () => { describe('Basic sequence parsing', () => { it('should parse a simple peptide sequence', () => { const input = 'PEPTIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(Object.keys(mods).length).toBe(0); expect(globalMods.length).toBe(0); expect(ambiguities.length).toBe(0); }); }); describe('Terminal modifications', () => { it('should parse N-terminal modification', () => { const input = '[Acetyl]-PEPTIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods[-1].length).toBe(1); expect(mods[-1][0].modValue.primaryValue).toBe('Acetyl'); expect(mods[-1][0].modType).toBe('terminal'); }); it('should parse C-terminal modification', () => { const input = 'PEPTIDE-[Amidated]'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods[-2].length).toBe(1); expect(mods[-2][0].modValue.primaryValue).toBe('Amidated'); expect(mods[-2][0].modType).toBe('terminal'); }); it('should parse both terminal modifications', () => { const input = '[Acetyl]-PEPTIDE-[Amidated]'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods[-1].length).toBe(1); expect(mods[-2].length).toBe(1); }); }); describe('Global modifications', () => { it('should parse fixed modifications', () => { const input = '<Carbamidomethyl@C>PEPCTIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPCTIDE'); expect(globalMods.length).toBe(1); expect(globalMods[0].modValue.primaryValue).toBe('Carbamidomethyl'); expect(globalMods[0].targetResidues).toEqual(['C']); expect(globalMods[0].modType).toBe('global'); expect(globalMods[0].globalModType).toBe('fixed'); }); it('should parse isotope labeling', () => { const input = '<15N>PEPTIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(globalMods.length).toBe(1); expect(globalMods[0].modValue.primaryValue).toBe('15N'); expect(globalMods[0].globalModType).toBe('isotope'); }); it('should parse multiple global modifications', () => { const input = '<Carbamidomethyl@C><15N>PEPCTIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(globalMods.length).toBe(2); }); }); describe('Site-specific modifications', () => { it('should parse single modification', () => { const input = 'PEP[Phospho]TIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods[2].length).toBe(1); expect(mods[2][0].modValue.primaryValue).toBe('Phospho'); }); it('should parse multiple modifications', () => { const input = 'PE[Phospho]PT[Phospho]IDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods['1'].length).toBe(1); expect(mods['3'].length).toBe(1); }); it('should parse mass shift modifications', () => { const input = 'PEP[+79.966]TIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods[2].length).toBe(1); expect(mods[2][0].mass).toBeCloseTo(79.966); }); }); describe('Sequence ambiguities', () => { it('should parse sequence ambiguity notation', () => { const input = 'PEP(?AB)TIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(ambiguities.length).toBe(1); expect(ambiguities[0].value).toBe('AB'); expect(ambiguities[0].position).toBe(0); }); }); describe('Labile modifications', () => { it('should parse labile modifications', () => { const input = '{Glycan:HexNAc}PEPTIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods[-3].length).toBe(1); expect(mods[-3][0].modValue.primaryValue).toBe('HexNAc'); expect(mods[-3][0].modValue.pipeValues[0].isValidGlycan).toBe(true); expect(mods[-3][0].modType).toBe('labile'); }); }); describe('Unknown position modifications', () => { it('should parse unknown position modifications', () => { const input = '[Phospho]?PEPTIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods[-4].length).toBe(1); expect(mods[-4][0].modValue.primaryValue).toBe('Phospho'); expect(mods[-4][0].modType).toBe('unknown_position'); }); it('should parse multiple unknown position modifications', () => { const input = '[Phospho][Acetyl]?PEPTIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods[-4].length).toBe(2); }); }); describe('Range modifications', () => { it('should parse range modifications', () => { const input = 'PE(PTI)DE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); // No modifications yet, just testing the range parsing }); it('should parse range with modifications', () => { const input = 'PE(PTI)[Phospho]DE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods[2].length).toBe(1); expect(mods[3].length).toBe(1); expect(mods[4].length).toBe(1); expect(mods[2][0].inRange).toBe(true); }); }); describe('Crosslinks and branches', () => { it('should parse crosslinks', () => { const input = 'PEPTIDE[DSS#XL1]KLMN[#XL1]'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDEKLMN'); expect(mods[6][0].crosslinkId).toBe('XL1'); expect(mods[10][0].isCrosslinkRef).toBe(true); }); it('should parse branch modifications', () => { const input = 'PEPTIDE[Glycan#BRANCH]K[#BRANCH]'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDEK'); expect(mods[6][0].modValue.isBranch).toBe(true); expect(mods[7][0].modValue.isBranchRef).toBe(true); }); }); describe('Ambiguity groups', () => { it('should parse ambiguity groups', () => { const input = 'PEPT[Phospho#1]IDE[Phospho#1]'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods[3][0].ambiguityGroup).toBe('1'); expect(mods[6][0].ambiguityGroup).toBe('1'); }); it('should parse ambiguity groups with localization scores', () => { const input = 'PEPT[Phospho#1(0.8)]IDE[Phospho#1(0.2)]'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(mods[3][0].localizationScore).toBe(0.8); expect(mods[6][0].localizationScore).toBe(0.2); }); it('should parse ambiguity reference', () => { const input = 'PEPT[Phospho#1]IDE[#1]'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(mods[3][0].ambiguityGroup).toBe('1'); expect(mods[6][0].ambiguityGroup).toBe('1'); expect(mods[6][0].isAmbiguityRef).toBe(true); }); }); describe('Complex examples', () => { it('should parse a complex ProForma string with multiple features', () => { const input = '<Carbamidomethyl@C>[Acetyl]-PEPC[+57.021]T[Phospho]IDE-[Amidated]'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPCTIDE'); expect(globalMods.length).toBe(1); expect(mods[-1]).toBeDefined(); // N-term mod expect(mods[-2]).toBeDefined(); // C-term mod expect(mods[3]).toBeDefined(); // Cysteine mod expect(mods[4]).toBeDefined(); // Threonine phosphorylation }); }); describe('INFO tags support', () => { it('should parse basic INFO tags', () => { const input = 'ELVIS[Phospho|INFO:newly discovered]K'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('ELVISK'); expect(mods[4].length).toBe(1); expect(mods[4][0].modValue.primaryValue).toBe('Phospho'); expect(mods[4][0].modValue.infoTags.length).toBe(1); expect(mods[4][0].modValue.infoTags[0]).toBe('newly discovered'); }); it('should parse multiple INFO tags', () => { const input = 'ELVIS[Phospho|INFO:newly discovered|INFO:Created on 2021-06]K'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('ELVISK'); expect(mods[4].length).toBe(1); expect(mods[4][0].modValue.primaryValue).toBe('Phospho'); expect(mods[4][0].modValue.infoTags.length).toBe(2); expect(mods[4][0].modValue.infoTags[0]).toBe('newly discovered'); expect(mods[4][0].modValue.infoTags[1]).toBe('Created on 2021-06'); }); it('should parse N-terminal modifications with INFO tags', () => { const input = '[Acetyl|INFO:Added during processing]-PEPTIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods[-1].length).toBe(1); expect(mods[-1][0].modValue.primaryValue).toBe('Acetyl'); expect(mods[-1][0].modValue.infoTags.length).toBe(1); expect(mods[-1][0].modValue.infoTags[0]).toBe('Added during processing'); }); it('should parse C-terminal modifications with INFO tags', () => { const input = 'PEPTIDE-[Amidated|INFO:Common C-terminal mod]'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods[-2].length).toBe(1); expect(mods[-2][0].modValue.primaryValue).toBe('Amidated'); expect(mods[-2][0].modValue.infoTags.length).toBe(1); expect(mods[-2][0].modValue.infoTags[0]).toBe('Common C-terminal mod'); }); it('should parse global isotope modifications with INFO tags', () => { const input = '<13C|INFO:Stable isotope labeling>PEPTIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(globalMods.length).toBe(1); expect(globalMods[0].modValue.primaryValue).toBe('13C'); expect(globalMods[0].globalModType).toBe('isotope'); expect(globalMods[0].modValue.infoTags.length).toBe(1); expect(globalMods[0].modValue.infoTags[0]).toBe('Stable isotope labeling'); }); it('should parse global fixed modifications with INFO tags', () => { const input = '<[Carbamidomethyl|INFO:Standard alkylation]@C>PEPTCDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTCDE'); expect(globalMods.length).toBe(1); expect(globalMods[0].modValue.primaryValue).toBe('Carbamidomethyl'); expect(globalMods[0].globalModType).toBe('fixed'); expect(globalMods[0].targetResidues).toEqual(['C']); expect(globalMods[0].modValue.infoTags.length).toBe(1); expect(globalMods[0].modValue.infoTags[0]).toBe('Standard alkylation'); }); it('should parse complex combinations with multiple INFO tags', () => { const input = '<[Carbamidomethyl|INFO:Standard alkylation]@C>[Acetyl|INFO:Added during processing]-PEPTC[+57.021|INFO:Mass verified]DE-[Amidated|INFO:Common C-terminal mod]'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTCDE'); // Check global mod expect(globalMods.length).toBe(1); expect(globalMods[0].modValue.primaryValue).toBe('Carbamidomethyl'); expect(globalMods[0].modValue.infoTags.length).toBe(1); expect(globalMods[0].modValue.infoTags[0]).toBe('Standard alkylation'); // Check N-terminal mod expect(mods[-1].length).toBe(1); expect(mods[-1][0].modValue.primaryValue).toBe('Acetyl'); expect(mods[-1][0].modValue.infoTags.length).toBe(1); expect(mods[-1][0].modValue.infoTags[0]).toBe('Added during processing'); // Check C-terminal mod expect(mods[-2].length).toBe(1); expect(mods[-2][0].modValue.primaryValue).toBe('Amidated'); expect(mods[-2][0].modValue.infoTags.length).toBe(1); expect(mods[-2][0].modValue.infoTags[0]).toBe('Common C-terminal mod'); // Check residue mod expect(mods[4].length).toBe(1); expect(mods[4][0].mass).toBeCloseTo(57.021); expect(mods[4][0].modValue.infoTags.length).toBe(1); expect(mods[4][0].modValue.infoTags[0]).toBe('Mass verified'); }); it('should handle INFO tags with special characters', () => { const input = 'PEP[Phospho|INFO:MS/MS score=0.98|INFO:RT=34.5 min]TIDE'; const [sequence, mods, globalMods, ambiguities] = proforma_1.ProFormaParser.parse(input); expect(sequence).toBe('PEPTIDE'); expect(mods[2].length).toBe(1); expect(mods[2][0].modValue.primaryValue).toBe('Phospho'); expect(mods[2][0].modValue.infoTags.length).toBe(2); expect(mods[2][0].modValue.infoTags[0]).toBe('MS/MS score=0.98'); expect(mods[2][0].modValue.infoTags[1]).toBe('RT=34.5 min'); }); }); });