sequaljs
Version:
JavaScript/TypeScript library for parsing and manipulating ProForma peptide sequence notation
272 lines (271 loc) • 16.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const sequence_1 = require("../sequence");
describe("ProForma 2.1: Integration Tests - Complex Scenarios", () => {
describe("Named Entities + Multiple Features", () => {
test("should handle peptidoform name with terminal global mods and charge", () => {
const seq = sequence_1.Sequence.fromProforma("(>TMT-labeled peptide)<[TMT6plex]@K,N-term>PEPTIDEK/2");
expect(seq.peptidoformName).toBe("TMT-labeled peptide");
expect(seq.globalMods.length).toBe(1);
expect(seq.globalMods[0].targetResidues).toContain("K");
expect(seq.globalMods[0].targetResidues).toContain("N-term");
expect(seq.charge).toBe(2);
});
test("should handle all three naming levels with modifications", () => {
const seq = sequence_1.Sequence.fromProforma("(>>>Chimeric Spectrum 1234)(>>Precursor z=2)(>Phospho-peptide)<[Phospho]@S,T,Y>PEPT[Oxidation]IDES/2");
expect(seq.compoundIonName).toBe("Chimeric Spectrum 1234");
expect(seq.peptidoformIonName).toBe("Precursor z=2");
expect(seq.peptidoformName).toBe("Phospho-peptide");
expect(seq.globalMods.length).toBe(1);
expect(seq.seq[3].mods[0].value).toBe("Oxidation");
expect(seq.charge).toBe(2);
});
test("should handle named entity with labile glycans", () => {
const seq = sequence_1.Sequence.fromProforma("(>Glycopeptide){Glycan:{C8H13N1O5}1Hex2}PEPN[Glycan:HexNAc2Hex3]TIDE");
expect(seq.peptidoformName).toBe("Glycopeptide");
const labileMods = seq.mods.get(-3);
expect(labileMods).toBeDefined();
expect(labileMods[0].modValue.pipeValues[0].isValidGlycan).toBe(true);
expect(seq.seq[3].mods[0].source).toBe("Glycan");
});
});
describe("Terminal Global Modifications + Complex Scenarios", () => {
test("should handle multiple terminal global mods with placement controls", () => {
const seq = sequence_1.Sequence.fromProforma("<[TMT6plex|Limit:1]@K,N-term><[Oxidation|Position:M,C]@M,C-term:G>MTPEILTCNSIGCLKG");
expect(seq.globalMods.length).toBe(2);
expect(seq.globalMods[0].targetResidues).toContain("K");
expect(seq.globalMods[0].targetResidues).toContain("N-term");
expect(seq.globalMods[0].getLimitPerPosition()).toBe(1);
expect(seq.globalMods[1].targetResidues).toContain("M");
expect(seq.globalMods[1].targetResidues).toContain("C-term:G");
});
test("should handle terminal global mods with ambiguous modifications", () => {
const seq = sequence_1.Sequence.fromProforma("<[Gln->pyro-Glu]@N-term:Q>QPEPTIDE[Phospho#1]S[#1]T");
expect(seq.globalMods.length).toBe(1);
expect(seq.globalMods[0].targetResidues).toEqual(["N-term:Q"]);
expect(seq.seq[7].mods[0].ambiguityGroup).toBe("1");
expect(seq.seq[8].mods[0].isAmbiguityRef).toBe(true);
});
test("should handle terminal global mods with charge states", () => {
const seq = sequence_1.Sequence.fromProforma("<[Acetyl]@N-term><[TMT6plex]@K>PEPTIDEK/2");
expect(seq.globalMods.length).toBe(2);
expect(seq.globalMods[0].targetResidues).toEqual(["N-term"]);
expect(seq.globalMods[1].targetResidues).toEqual(["K"]);
expect(seq.charge).toBe(2);
});
});
describe("Custom Monosaccharides + Complex Glycosylation", () => {
test("should handle mixed custom and standard monosaccharides", () => {
const seq = sequence_1.Sequence.fromProforma("PEPN[Glycan:HexNAc2{C8H13N1O5Na1:z+1}1Hex3]TIDE");
expect(seq.seq[3].mods[0].modValue.pipeValues[0].isValidGlycan).toBe(true);
expect(seq.seq[3].mods[0].source).toBe("Glycan");
});
test("should handle labile and static custom monosaccharides together", () => {
const seq = sequence_1.Sequence.fromProforma("{Glycan:{C11H17N1O9}1Hex2}PEPN[Glycan:{C8H13[15N1]O5}2Hex1]TIDE");
const labileMods = seq.mods.get(-3);
expect(labileMods).toBeDefined();
expect(labileMods[0].modValue.pipeValues[0].isValidGlycan).toBe(true);
expect(seq.seq[3].mods[0].modValue.pipeValues[0].isValidGlycan).toBe(true);
expect(seq.seq[3].mods[0].modValue.pipeValues[0].value).toContain("[15N1]");
});
test("should handle custom monosaccharides in sequences", () => {
const seq = sequence_1.Sequence.fromProforma("NSTPEPN[Glycan:{C8H13N1O5}1Hex2]TIDE");
expect(seq.seq[6].mods[0].modValue.pipeValues[0].isValidGlycan).toBe(true);
expect(seq.seq[6].mods[0].source).toBe("Glycan");
});
});
describe("Charged Formulas + Ion Notation", () => {
test("should handle charged formula with ion type notation", () => {
const seq = sequence_1.Sequence.fromProforma("PEPTIDE[Formula:Zn1:z+2]-[b-type-ion]");
expect(seq.seq[6].mods[0].modValue.pipeValues[0].charge).toBe("z+2");
expect(seq.seq[6].mods[0].modValue.pipeValues[0].chargeValue).toBe(2);
const cTermMods = seq.mods.get(-2);
expect(cTermMods).toBeDefined();
expect(cTermMods[0].isIonType).toBe(true);
});
test("should handle multiple charged formulas with different charges", () => {
const seq = sequence_1.Sequence.fromProforma("PEPT[Formula:C2H3NO:z-1]IDE[Formula:Zn1:z+2]K");
expect(seq.seq[3].mods[0].modValue.pipeValues[0].chargeValue).toBe(-1);
expect(seq.seq[6].mods[0].modValue.pipeValues[0].chargeValue).toBe(2);
});
test("should handle charged glycan with ion notation", () => {
const seq = sequence_1.Sequence.fromProforma("N[Glycan:{C8H13N1O5Na1:z+1}1Hex2]PEPTIDE-[y-type-ion]");
expect(seq.seq[0].mods[0].modValue.pipeValues[0].isValidGlycan).toBe(true);
const cTermMods = seq.mods.get(-2);
expect(cTermMods[0].isIonType).toBe(true);
});
});
describe("Placement Controls + Advanced Features", () => {
test("should handle basic placement controls on fixed position mods", () => {
const seq = sequence_1.Sequence.fromProforma("PEPT[Phospho|INFO:High confidence]IDE");
expect(seq.seq[3].mods[0].value).toBe("Phospho");
expect(seq.seq[3].mods[0].infoTags.length).toBeGreaterThan(0);
});
test("should handle multiple modifications with ambiguity", () => {
const seq = sequence_1.Sequence.fromProforma("PEPT[Phospho#G1]IDE[#G1]");
expect(seq.seq[3].mods[0].ambiguityGroup).toBe("G1");
expect(seq.seq[6].mods[0].isAmbiguityRef).toBe(true);
});
});
describe("Chimeric Spectra with ProForma 2.1", () => {
test("should handle chimeric with named entities", () => {
const seq = sequence_1.Sequence.fromProforma("(>>>Chimeric Scan 5678)(>Peptide1)PEPTIDE+SEQUENCEK");
expect(seq.compoundIonName).toBe("Chimeric Scan 5678");
expect(seq.peptidoformName).toBe("Peptide1");
expect(seq.isChimeric).toBe(true);
});
});
describe("Multi-Chain Sequences with ProForma 2.1", () => {
test("should handle multi-chain with naming level on first chain", () => {
const seq = sequence_1.Sequence.fromProforma("(>>>Disulfide-linked)(>>Ion pair)(>Chain1)PEPTIDEC//CSEQUENCE");
expect(seq.compoundIonName).toBe("Disulfide-linked");
expect(seq.peptidoformIonName).toBe("Ion pair");
expect(seq.isMultiChain).toBe(true);
expect(seq.chains[0].peptidoformName).toBe("Chain1");
});
test("should handle multi-chain with different terminal global mods", () => {
const seq = sequence_1.Sequence.fromProforma("<[Acetyl]@N-term>PEPTIDE//<[TMT6plex]@K,N-term>KSEQUENCEK");
expect(seq.isMultiChain).toBe(true);
expect(seq.chains[0].globalMods[0].targetResidues).toEqual(["N-term"]);
expect(seq.chains[1].globalMods[0].targetResidues).toContain("K");
expect(seq.chains[1].globalMods[0].targetResidues).toContain("N-term");
});
});
describe("Real-World Complex Scenarios", () => {
test("should handle TMT-labeled phosphopeptide with multiple PTMs", () => {
const seq = sequence_1.Sequence.fromProforma("(>TMT-labeled phosphopeptide)<[TMT6plex]@K,N-term><[Oxidation]@M>MTPEILTS[Phospho]CNSIGCLK/2");
expect(seq.peptidoformName).toBe("TMT-labeled phosphopeptide");
expect(seq.globalMods.length).toBe(2);
expect(seq.globalMods[0].targetResidues).toContain("N-term");
expect(seq.globalMods[1].targetResidues).toEqual(["M"]);
expect(seq.seq[7].mods[0].value).toBe("Phospho");
expect(seq.charge).toBe(2);
});
test("should handle glycopeptide with multiple glycosylation sites", () => {
const seq = sequence_1.Sequence.fromProforma("{Glycan:Hex1HexNAc1}N[Glycan:{C8H13N1O5}2Hex3HexNAc2]GSTN[Glycan:HexNAc2Hex3NeuAc1]VTPEPTIDE");
const labileMods = seq.mods.get(-3);
expect(labileMods).toBeDefined();
expect(seq.seq[0].mods[0].modValue.pipeValues[0].isValidGlycan).toBe(true);
expect(seq.seq[4].mods[0].modValue.pipeValues[0].isValidGlycan).toBe(true);
});
test("should handle complex proteoform with multiple modification types", () => {
const seq = sequence_1.Sequence.fromProforma("(>Ubiquitinated protein)[Acetyl]-MRSGSHHHHHHGSPEPTM[Oxidation]IDEK[Ubiquitin#BRANCH]SEQUENCE-[Amidated]");
expect(seq.peptidoformName).toBe("Ubiquitinated protein");
const nTermMods = seq.mods.get(-1);
expect(nTermMods[0].value).toBe("Acetyl");
expect(seq.seq[17].mods[0].value).toBe("Oxidation");
expect(seq.seq[21].mods[0].isBranch).toBe(true);
const cTermMods = seq.mods.get(-2);
expect(cTermMods[0].value).toBe("Amidated");
});
test("should handle metal-binding peptide with charged formulas", () => {
const seq = sequence_1.Sequence.fromProforma("(>Zinc finger peptide)CAQECGK[Formula:Zn1:z+2]SFTSALK[Formula:Zn1:z+2]SRHK/3");
expect(seq.peptidoformName).toBe("Zinc finger peptide");
expect(seq.seq[6].mods[0].modValue.pipeValues[0].chargeValue).toBe(2);
expect(seq.seq[13].mods[0].modValue.pipeValues[0].chargeValue).toBe(2);
expect(seq.charge).toBe(3);
});
test("should handle peptide with unknown position mods and basic placement controls", () => {
const seq = sequence_1.Sequence.fromProforma("[Phospho]^3[Oxidation]^2?MSTPEPTMSTY");
const unknownMods = seq.mods.get(-4);
expect(unknownMods.length).toBe(5);
expect(unknownMods[0].value).toBe("Phospho");
expect(unknownMods[3].value).toBe("Oxidation");
});
});
describe("Edge Cases and Complex Combinations", () => {
test("should handle all ProForma 2.1 features in one sequence", () => {
const seq = sequence_1.Sequence.fromProforma("(>>>MS2 Spectrum)(>>Precursor z=2)(>Complex peptide)<[TMT6plex]@K,N-term><[Gln->pyro-Glu]@N-term:Q>" +
"{Glycan:{C8H13N1O5}1}[Acetyl]-QN[Glycan:HexNAc2{C11H17N1O9}1]PEPTM[Oxidation|INFO:High confidence]IDEK[Formula:Zn1:z+2]-[b-type-ion]/2");
expect(seq.compoundIonName).toBe("MS2 Spectrum");
expect(seq.peptidoformIonName).toBe("Precursor z=2");
expect(seq.peptidoformName).toBe("Complex peptide");
expect(seq.globalMods.length).toBe(2);
const labileMods = seq.mods.get(-3);
expect(labileMods).toBeDefined();
expect(labileMods[0].modValue.pipeValues[0].isValidGlycan).toBe(true);
const nTermMods = seq.mods.get(-1);
expect(nTermMods[0].value).toBe("Acetyl");
expect(seq.seq[1].mods[0].modValue.pipeValues[0].isValidGlycan).toBe(true);
expect(seq.seq[6].mods[0].infoTags.length).toBeGreaterThan(0);
expect(seq.seq[10].mods[0].modValue.pipeValues[0].chargeValue).toBe(2);
const cTermMods = seq.mods.get(-2);
expect(cTermMods[0].isIonType).toBe(true);
expect(seq.charge).toBe(2);
});
test("should round-trip complex integrated sequences", () => {
const testCases = [
"(>Named peptide)<[TMT6plex]@K,N-term>PEPTIDEK/2",
"{Glycan:{C8H13N1O5}1Hex2}N[Glycan:HexNAc2]PEPTIDE",
"<[Gln->pyro-Glu]@N-term:Q>QPEPTM[Oxidation]IDE-[b-type-ion]",
"[Phospho]^2?STPEPTIDE",
];
for (const original of testCases) {
const seq = sequence_1.Sequence.fromProforma(original);
const proforma = seq.toProforma();
const seq2 = sequence_1.Sequence.fromProforma(proforma);
const proforma2 = seq2.toProforma();
expect(proforma).toBe(original);
expect(proforma2).toBe(original);
}
});
test("should handle terminal modifications with global terminal mods", () => {
const seq = sequence_1.Sequence.fromProforma("<[Acetyl]@N-term>[Carbamyl]-PEPTIDE-[Methyl]");
expect(seq.globalMods.length).toBe(1);
expect(seq.globalMods[0].targetResidues).toEqual(["N-term"]);
const nTermMods = seq.mods.get(-1);
expect(nTermMods[0].value).toBe("Carbamyl");
const cTermMods = seq.mods.get(-2);
expect(cTermMods[0].value).toBe("Methyl");
});
test("should handle sequence ambiguity with ProForma 2.1 features", () => {
const seq = sequence_1.Sequence.fromProforma("(>Ambiguous peptide)<[TMT6plex]@K>PEPT(?IL)DE[Formula:Zn1:z+2]K/2");
expect(seq.peptidoformName).toBe("Ambiguous peptide");
expect(seq.globalMods.length).toBe(1);
expect(seq.sequenceAmbiguities.length).toBe(1);
expect(seq.sequenceAmbiguities[0].value).toBe("IL");
expect(seq.seq[5].mods[0].modValue.pipeValues[0].chargeValue).toBe(2);
expect(seq.charge).toBe(2);
});
test("should handle isotope labels with ProForma 2.1 features", () => {
const seq = sequence_1.Sequence.fromProforma("(>Heavy labeled)<[Label:13C(6)15N(2)]@K,R>PEPTIDER");
expect(seq.peptidoformName).toBe("Heavy labeled");
expect(seq.globalMods.length).toBe(1);
expect(seq.globalMods[0].value).toContain("13C");
expect(seq.globalMods[0].value).toContain("15N");
});
});
describe("Serialization Integrity", () => {
test("should maintain order of multiple global modifications", () => {
const original = "<[TMT6plex]@K,N-term><[Oxidation]@M><[Phospho]@S,T,Y>MSTPEPTIDEK";
const seq = sequence_1.Sequence.fromProforma(original);
const proforma = seq.toProforma();
expect(proforma).toBe(original);
expect(seq.globalMods.length).toBe(3);
});
test("should maintain complex nested structures", () => {
const original = "(>>>C1)(>>I1)(>P1)<[Mod]@N-term>{Glycan:Hex1}[Ac]-N[Gly:H1]S-[Am]/2";
const seq = sequence_1.Sequence.fromProforma(original);
const proforma = seq.toProforma();
expect(seq.compoundIonName).toBe("C1");
expect(seq.peptidoformIonName).toBe("I1");
expect(seq.peptidoformName).toBe("P1");
expect(proforma).toBe(original);
});
});
describe("Performance and Stress Tests", () => {
test("should handle very long sequence with multiple modifications", () => {
const longSeq = "M".repeat(50);
const seq = sequence_1.Sequence.fromProforma(`<[Oxidation]@M>${longSeq.split("").map((aa, i) => i % 5 === 0 ? `${aa}[Oxidation]` : aa).join("")}`);
expect(seq.globalMods.length).toBe(1);
expect(seq.seq.length).toBe(50);
const modsCount = seq.seq.filter(aa => aa.mods.length > 0).length;
expect(modsCount).toBe(10);
});
test("should handle many unknown position modifications", () => {
const seq = sequence_1.Sequence.fromProforma("[Phospho|Position:S,T,Y]^10?SYTSTPEPTIDESTSTY");
const unknownMods = seq.mods.get(-4);
expect(unknownMods.length).toBe(10);
});
});
});