public void WriteModificationNameAndIdentifiers() { // RESID var term = new ProFormaTerm("SEQUENCE", tags: new[] { new ProFormaTag(2, new[] { new ProFormaDescriptor(ProFormaKey.Identifier, ProFormaEvidenceType.Resid, "AA0420") }), new ProFormaTag(4, new[] { new ProFormaDescriptor(ProFormaKey.Name, ProFormaEvidenceType.Resid, "Test") }), }); var result = _writer.WriteString(term); Assert.AreEqual("SEQ[RESID:AA0420]UE[R:Test]NCE", result); // PSI-MOD term = new ProFormaTerm("SEQUENCE", tags: new[] { new ProFormaTag(2, new[] { new ProFormaDescriptor(ProFormaKey.Identifier, ProFormaEvidenceType.PsiMod, "MOD:00232") }), new ProFormaTag(4, new[] { new ProFormaDescriptor(ProFormaKey.Name, ProFormaEvidenceType.PsiMod, "Test") }), }); result = _writer.WriteString(term); Assert.AreEqual("SEQ[MOD:00232]UE[M:Test]NCE", result); // Unimod term = new ProFormaTerm("SEQUENCE", tags: new[] { new ProFormaTag(2, new[] { new ProFormaDescriptor(ProFormaKey.Identifier, ProFormaEvidenceType.Unimod, "UNIMOD:15") }), new ProFormaTag(4, new[] { new ProFormaDescriptor(ProFormaKey.Name, ProFormaEvidenceType.Unimod, "Test") }), }); result = _writer.WriteString(term); Assert.AreEqual("SEQ[UNIMOD:15]UE[U:Test]NCE", result); }
public void WriteSequenceOnly() { var term = new ProFormaTerm("SEQUENCE"); var result = _writer.WriteString(term); Assert.AreEqual(term.Sequence, result); }
public void IgnoreMultipleTags() { var modificationLookup = new CompositeModificationLookup(new[] { new IgnoreKeyModificationLookup(ProFormaKey.Mass), new IgnoreKeyModificationLookup(ProFormaKey.Info) }); var term = new ProFormaTerm("SEQVENCE", tags: new List <ProFormaTag> { new ProFormaTag(3, new[] { new ProFormaDescriptor(ProFormaKey.Mass, "14.05") }), new ProFormaTag(5, new[] { new ProFormaDescriptor(ProFormaKey.Info, "not important") }) });; var proteoform = _factory.CreateProteoformGroup(term, modificationLookup); Assert.IsNull(proteoform.LocalizedModifications); term = new ProFormaTerm("SEQVENCE", tags: new List <ProFormaTag> { new ProFormaTag(3, new[] { new ProFormaDescriptor(ProFormaKey.Mass, "14.05"), new ProFormaDescriptor(ProFormaKey.Info, "not important") }) }); proteoform = _factory.CreateProteoformGroup(term, modificationLookup); Assert.IsNull(proteoform.LocalizedModifications); }
public void WriteAmbiguousPossibleSitesDescriptors() { var term = new ProFormaTerm("SEQUENCE", tagGroups: new[] { new ProFormaTagGroup("test", ProFormaKey.Mass, "+14.05", new[] { new ProFormaMembershipDescriptor(2), new ProFormaMembershipDescriptor(5), }), }); var result = _writer.WriteString(term); Assert.AreEqual("SEQ[+14.05#test]UEN[#test]CE", result); // With weights term = new ProFormaTerm("SEQUENCE", tagGroups: new[] { new ProFormaTagGroup("test", ProFormaKey.Mass, "+14.05", new[] { new ProFormaMembershipDescriptor(2, 0.9), new ProFormaMembershipDescriptor(5, 0.1), }), }); result = _writer.WriteString(term); Assert.AreEqual("SEQ[+14.05#test(0.9)]UEN[#test(0.1)]CE", result); }
public void HandleTerminalModificationNameTag() { const string sequence = "SEQVENCE"; var modificationLookup = new BrnoModificationLookup(_elementProvider); ProFormaDescriptor descriptor = this.CreateBrnoDescriptor("ac"); var term = new ProFormaTerm(sequence, null, new[] { descriptor }, null, null); var proteoform = _factory.CreateProteoformGroup(term, modificationLookup); Assert.IsNull(proteoform.LocalizedModifications); Assert.IsNotNull(proteoform.NTerminalModification); Assert.IsNull(proteoform.CTerminalModification); // Residue masses plus modification plus water (approx) Assert.AreEqual(978.36, proteoform.GetMass(MassType.Monoisotopic), 0.01); Assert.AreEqual(978.98, proteoform.GetMass(MassType.Average), 0.01); // C terminal case term = new ProFormaTerm(sequence, null, null, new[] { descriptor }, null); proteoform = _factory.CreateProteoformGroup(term, modificationLookup); Assert.IsNull(proteoform.LocalizedModifications); Assert.IsNull(proteoform.NTerminalModification); Assert.IsNotNull(proteoform.CTerminalModification); // Residue masses plus modification plus water (approx) Assert.AreEqual(978.36, proteoform.GetMass(MassType.Monoisotopic), 0.01); Assert.AreEqual(978.98, proteoform.GetMass(MassType.Average), 0.01); }
public void WriteLabileModifications() { var term = new ProFormaTerm("SEQUENCE", labileDescriptors: new[] { new ProFormaDescriptor(ProFormaKey.Glycan, "Hex") }, tags: new[] { new ProFormaTag(2, new[] { new ProFormaDescriptor(ProFormaKey.Name, ProFormaEvidenceType.Unimod, "Hydroxylation") }) }); var result = _writer.WriteString(term); Assert.AreEqual("{Glycan:Hex}SEQ[U:Hydroxylation]UENCE", result); // Labile and terminal mods term = new ProFormaTerm("SEQUENCE", labileDescriptors: new[] { new ProFormaDescriptor(ProFormaKey.Glycan, "Hex") }, nTerminalDescriptors: new[] { new ProFormaDescriptor("iTRAQ4plex") }, tags: new[] { new ProFormaTag(2, new[] { new ProFormaDescriptor(ProFormaKey.Name, ProFormaEvidenceType.Unimod, "Hydroxylation") }) }); result = _writer.WriteString(term); Assert.AreEqual("{Glycan:Hex}[iTRAQ4plex]-SEQ[U:Hydroxylation]UENCE", result); }
public void TagsWithoutLookupThrowException() { var term = new ProFormaTerm("SEQVENCE", tags: new List <ProFormaTag> { new ProFormaTag(3, new[] { new ProFormaDescriptor(ProFormaKey.Mass, "14.05") }) }); Assert.Throws <ProteoformGroupCreateException>(() => _factory.CreateProteoformGroup(term, null)); }
public void WriteSingleTag() { var term = new ProFormaTerm("SEQUENCE", tags: new[] { new ProFormaTag(2, new[] { new ProFormaDescriptor(ProFormaKey.Info, "test") }) }); var result = _writer.WriteString(term); Assert.AreEqual("SEQ[Info:test]UENCE", result); }
public void WriteMultipleTags() { var term = new ProFormaTerm("SEQUENCE", tags: new[] { new ProFormaTag(2, new[] { new ProFormaDescriptor(ProFormaKey.Info, "test") }), new ProFormaTag(5, new[] { new ProFormaDescriptor(ProFormaKey.Mass, "+14.05") }), }); var result = _writer.WriteString(term); Assert.AreEqual("SEQ[Info:test]UEN[+14.05]CE", result); }
public void HandleBadModificationName() { var modificationLookup = new BrnoModificationLookup(_elementProvider); var term = new ProFormaTerm("SEQVENCE", tags: new List <ProFormaTag> { new ProFormaTag(3, new[] { this.CreateBrnoDescriptor("wrong") }) }); Assert.Throws <ProteoformModificationLookupException>(() => _factory.CreateProteoformGroup(term, modificationLookup)); }
public void IgnoreMassTag() { IProteoformModificationLookup modificationLookup = new IgnoreKeyModificationLookup(ProFormaKey.Mass); var term = new ProFormaTerm("SEQVENCE", tags: new List <ProFormaTag> { new ProFormaTag(3, new[] { new ProFormaDescriptor(ProFormaKey.Mass, "14.05") }) }); var proteoform = _factory.CreateProteoformGroup(term, modificationLookup); Assert.IsNull(proteoform.LocalizedModifications); }
public void WriteAmbiguousRangeDescriptors() { var term = new ProFormaTerm("SEQUENCE", tags: new[] { new ProFormaTag(2, 5, new[] { new ProFormaDescriptor(ProFormaKey.Mass, "+14.05"), }) }); var result = _writer.WriteString(term); Assert.AreEqual("SE(QUEN)[+14.05]CE", result); }
public void WriteAmbiguousUnlocalizedTags() { var term = new ProFormaTerm("SEQUENCE", unlocalizedTags: new[] { new ProFormaUnlocalizedTag(1, new[] { new ProFormaDescriptor(ProFormaKey.Mass, "+14.05"), }), }); var result = _writer.WriteString(term); Assert.AreEqual("[+14.05]?SEQUENCE", result); }
public void WriteUnlocalizedAmbiguousTagsTerminalMod() { var term = new ProFormaTerm("SEQUENCE", unlocalizedTags: new[] { new ProFormaUnlocalizedTag(1, new[] { new ProFormaDescriptor(ProFormaKey.Mass, "+14.05") }), }, nTerminalDescriptors: new[] { new ProFormaDescriptor(ProFormaKey.Info, "unknown") }); var result = _writer.WriteString(term); Assert.AreEqual("[+14.05]?[Info:unknown]-SEQUENCE", result); }
public void HandleFormalCharge() { var term = new ProFormaTerm("KEQVENCE", tags: new List <ProFormaTag> { new ProFormaTag(3, new[] { new ProFormaDescriptor(ProFormaKey.Identifier, ProFormaEvidenceType.Resid, "AA0074") }) }); var proteoform = _factory.CreateProteoformGroup(term, _residLookup); Assert.IsNotNull(proteoform.LocalizedModifications); // Residue masses plus water (approx) Assert.AreEqual(1019.46, proteoform.GetMass(MassType.Monoisotopic), 0.01); Assert.AreEqual(1020.12, proteoform.GetMass(MassType.Average), 0.01); }
public void WriteRangeAmbiguousTagsTerminalMod() { var term = new ProFormaTerm("SEQUENCE", tags: new[] { new ProFormaTag(2, 5, new[] { new ProFormaDescriptor(ProFormaKey.Mass, "+14.05"), }) }, nTerminalDescriptors: new[] { new ProFormaDescriptor(ProFormaKey.Info, "unknown") }); var result = _writer.WriteString(term); Assert.AreEqual("[Info:unknown]-SE(QUEN)[+14.05]CE", result); }
public void WritePossibleSitesAmbiguousTagsTerminalMod() { var term = new ProFormaTerm("SEQUENCE", tagGroups: new[] { new ProFormaTagGroup("test", ProFormaKey.Mass, "+14.05", new[] { new ProFormaMembershipDescriptor(2), new ProFormaMembershipDescriptor(5), }), }, nTerminalDescriptors: new[] { new ProFormaDescriptor(ProFormaKey.Info, "unknown") }); var result = _writer.WriteString(term); Assert.AreEqual("[Info:unknown]-SEQ[+14.05#test]UEN[#test]CE", result); }
public void NoTagsValid() { const string sequence = "SEQVENCE"; var term = new ProFormaTerm(sequence); var proteoform = _factory.CreateProteoformGroup(term, null); Assert.IsNotNull(proteoform.Residues); Assert.AreEqual(8, proteoform.Residues.Count); Assert.AreEqual(sequence, proteoform.GetSequence()); Assert.IsNull(proteoform.LocalizedModifications); // Residue masses plus water (approx) Assert.AreEqual(936.35, proteoform.GetMass(MassType.Monoisotopic), 0.01); Assert.AreEqual(936.95, proteoform.GetMass(MassType.Average), 0.01); }
public void WriteTerminalModsOnly() { var term = new ProFormaTerm("SEQUENCE", nTerminalDescriptors: new[] { new ProFormaDescriptor(ProFormaKey.Info, "test") }); var result = _writer.WriteString(term); Assert.AreEqual("[Info:test]-SEQUENCE", result); term = new ProFormaTerm("SEQUENCE", cTerminalDescriptors: new[] { new ProFormaDescriptor(ProFormaKey.Info, "test") }); result = _writer.WriteString(term); Assert.AreEqual("SEQUENCE-[Info:test]", result); term = new ProFormaTerm("SEQUENCE", nTerminalDescriptors: new[] { new ProFormaDescriptor(ProFormaKey.Info, "testN") }, cTerminalDescriptors: new[] { new ProFormaDescriptor(ProFormaKey.Info, "testC") }); result = _writer.WriteString(term); Assert.AreEqual("[Info:testN]-SEQUENCE-[Info:testC]", result); }
public void HandleModificationNameTag() { const string sequence = "SEQVENCE"; var modificationLookup = new BrnoModificationLookup(_elementProvider); var term = new ProFormaTerm(sequence, tags: new List <ProFormaTag> { new ProFormaTag(3, new[] { this.CreateBrnoDescriptor("ac") }) }); var proteoform = _factory.CreateProteoformGroup(term, modificationLookup); Assert.IsNotNull(proteoform.LocalizedModifications); Assert.AreEqual(1, proteoform.LocalizedModifications.Count); Assert.AreEqual(3, ((IProteoformLocalizedModification)proteoform.LocalizedModifications.Single()).ZeroBasedStartIndex); // Residue masses plus modification plus water (approx) Assert.AreEqual(978.36, proteoform.GetMass(MassType.Monoisotopic), 0.01); Assert.AreEqual(978.98, proteoform.GetMass(MassType.Average), 0.01); }
public void WriteGlobalModifications() { // Representation of isotopes var term = new ProFormaTerm("SEQUENCE", globalModifications: new[] { new ProFormaGlobalModification(new[] { new ProFormaDescriptor("13C") }, null) }); var result = _writer.WriteString(term); Assert.AreEqual("<13C>SEQUENCE", result); // Two isotopes term = new ProFormaTerm("SEQUENCE", globalModifications: new[] { new ProFormaGlobalModification(new[] { new ProFormaDescriptor("13C") }, null), new ProFormaGlobalModification(new[] { new ProFormaDescriptor("15N") }, null), }); result = _writer.WriteString(term); Assert.AreEqual("<13C><15N>SEQUENCE", result); // Fixed protein modifications (single target) term = new ProFormaTerm("SEQUENCE", globalModifications: new[] { new ProFormaGlobalModification(new[] { new ProFormaDescriptor(ProFormaKey.Identifier, ProFormaEvidenceType.PsiMod, "MOD:01090") }, new[] { 'C' }) }); result = _writer.WriteString(term); Assert.AreEqual("<[MOD:01090]@C>SEQUENCE", result); // Fixed protein modifications (multiple targets) term = new ProFormaTerm("SEQUENCE", globalModifications: new[] { new ProFormaGlobalModification(new[] { new ProFormaDescriptor(ProFormaKey.Name, "Oxidation") }, new[] { 'C', 'M' }) }); result = _writer.WriteString(term); Assert.AreEqual("<[Oxidation]@C,M>SEQUENCE", result); }
/// <summary>Generates a chemical proteoform hash for the specified proteoform.</summary> /// <param name="proForma">The ProForma.</param> /// <returns></returns> public IChemicalProteoformHash Generate(string proForma) { // Parse string into term ProFormaTerm originalProFormaTerm = this._proFormaParser.ParseString(proForma); // Check to see if this is only a sequence if (originalProFormaTerm.NTerminalDescriptors == null && originalProFormaTerm.CTerminalDescriptors == null && originalProFormaTerm.Tags == null && originalProFormaTerm.GlobalModifications == null && originalProFormaTerm.LabileDescriptors == null && originalProFormaTerm.TagGroups == null && originalProFormaTerm.UnlocalizedTags == null) { IProteoformGroup simpleGroup = this._proteoformGroupFactory.CreateProteoformGroup(originalProFormaTerm.Sequence); return(new ChemicalProteoformHash(originalProFormaTerm.Sequence, simpleGroup)); } // Create proteoform group (flattens all features into Ids) IProteoformGroup proteoformGroup = this._proteoformGroupFactory.CreateProteoformGroup(originalProFormaTerm, this._proteoformModificationLookup); ProFormaDescriptor?nTermDescriptor = this.CreateDescriptor(proteoformGroup.NTerminalModification); IList <ProFormaDescriptor>?nTermDescriptors = nTermDescriptor == null ? null : new[] { nTermDescriptor }; ProFormaDescriptor?cTermDescriptor = this.CreateDescriptor(proteoformGroup.CTerminalModification); IList <ProFormaDescriptor>?cTermDescriptors = cTermDescriptor == null ? null : new[] { cTermDescriptor }; IList <ProFormaTag>? tags = null; IList <ProFormaDescriptor>? labileDescriptors = null; IList <ProFormaUnlocalizedTag>? unlocalizedTags = null; IList <ProFormaTagGroup>? tagGroups = null; IList <ProFormaGlobalModification>?globalModifications = null; if (proteoformGroup.LocalizedModifications?.Count > 0) { foreach (var mod in proteoformGroup.LocalizedModifications) { ProFormaDescriptor?descriptor = this.CreateDescriptor(mod.ModificationDelta); if (descriptor != null) { tags ??= new List <ProFormaTag>(); tags.Add(new ProFormaTag(mod.ZeroBasedStartIndex, mod.ZeroBasedEndIndex, new[] { descriptor })); } } } if (proteoformGroup.UnlocalizedModifications?.Count > 0) { foreach (var mod in proteoformGroup.UnlocalizedModifications) { ProFormaDescriptor?descriptor = this.CreateDescriptor(mod.ModificationDelta); if (descriptor != null) { if (mod.IsLabile) { labileDescriptors ??= new List <ProFormaDescriptor>(); for (int i = 0; i < mod.Count; i++) { labileDescriptors.Add(descriptor); } } else { unlocalizedTags ??= new List <ProFormaUnlocalizedTag>(); unlocalizedTags.Add(new ProFormaUnlocalizedTag(mod.Count, new[] { descriptor })); } } } } if (proteoformGroup.ModificationGroups?.Count > 0) { foreach (var mod in proteoformGroup.ModificationGroups) { ProFormaDescriptor?descriptor = this.CreateDescriptor(mod.ModificationDelta); if (descriptor != null) { tagGroups ??= new List <ProFormaTagGroup>(); tagGroups.Add(new ProFormaTagGroup(mod.GroupName, descriptor.Key, descriptor.EvidenceType, descriptor.Value, mod.Members.Select(x => new ProFormaMembershipDescriptor(x.ZeroBasedStartIndex, x.ZeroBasedEndIndex, x.Weight)).ToList())); } } } if (proteoformGroup.GlobalModifications?.Count > 0) { foreach (var mod in proteoformGroup.GlobalModifications) { ProFormaDescriptor?descriptor = this.CreateDescriptor(mod.ModificationDelta); if (descriptor != null) { globalModifications ??= new List <ProFormaGlobalModification>(); globalModifications.Add(new ProFormaGlobalModification(new[] { descriptor }, mod.TargetAminoAcids)); } } } string?sequence = proteoformGroup.GetSequence(); if (sequence != null) { ProFormaTerm proFormaTerm = new(sequence, tags : tags?.OrderBy(t => t.Descriptors.First().Value).ToArray(), nTerminalDescriptors : nTermDescriptors, cTerminalDescriptors : cTermDescriptors, labileDescriptors : labileDescriptors, unlocalizedTags : unlocalizedTags, tagGroups : tagGroups, globalModifications : globalModifications); string hash = new ProFormaWriter().WriteString(proFormaTerm); return(new ChemicalProteoformHash(hash, proteoformGroup)); } throw new Exception("Cannot get amino acid sequence for the proteoform group."); }
/// <summary> /// Creates the proteoform group. /// </summary> /// <param name="term">The term.</param> /// <param name="modificationLookup">The modification lookup.</param> /// <returns></returns> /// <exception cref="ArgumentNullException">term</exception> /// <exception cref="ProteoformGroupCreateException"> /// Cannot lookup tag because lookup wasn't provided. /// or /// </exception> public IProteoformGroup CreateProteoformGroup(ProFormaTerm term, IProteoformModificationLookup modificationLookup) { if (term == null) { throw new ArgumentNullException(nameof(term)); } var residues = term.Sequence.Select(x => _residueProvider.GetResidue(x)).ToArray(); List <IProteoformLocalizedModification>? localizedModifications = null; List <IProteoformUnlocalizedModification>?unlocalizedModifications = null; List <IProteoformModificationGroup>? modificationGroups = null; List <IProteoformGlobalModification>? globalModifications = null; IProteoformMassDelta?nTerminalModification = this.GetModification(term.NTerminalDescriptors, modificationLookup, "Multiple N Terminal Modifications"); IProteoformMassDelta?cTerminalModification = this.GetModification(term.CTerminalDescriptors, modificationLookup, "Multiple C Terminal Modifications"); if (term.Tags?.Count > 0) { foreach (var tag in term.Tags) { IProteoformMassDelta?delta = this.GetModification(tag.Descriptors, modificationLookup, $"Multiple modifications at index: {tag.ZeroBasedStartIndex}"); if (delta != null) { localizedModifications ??= new List <IProteoformLocalizedModification>(); localizedModifications.Add(new LocalizedModification(delta, tag.ZeroBasedStartIndex, tag.ZeroBasedEndIndex)); } } } if (term.LabileDescriptors?.Count > 0) { foreach (var item in term.LabileDescriptors) { IProteoformMassDelta?delta = this.GetModification(item, modificationLookup); if (delta != null) { unlocalizedModifications ??= new List <IProteoformUnlocalizedModification>(); unlocalizedModifications.Add(new UnlocalizedModification(delta, 1, true)); } } } if (term.UnlocalizedTags?.Count > 0) { foreach (var item in term.UnlocalizedTags) { IProteoformMassDelta?delta = this.GetModification(item.Descriptors, modificationLookup, "Multiple unlocalized descriptors on same tag."); if (delta != null) { unlocalizedModifications ??= new List <IProteoformUnlocalizedModification>(); unlocalizedModifications.Add(new UnlocalizedModification(delta, item.Count, false)); } } } if (term.TagGroups?.Count > 0) { foreach (var item in term.TagGroups) { IProteoformMassDelta?delta = this.GetModification(item, modificationLookup); if (delta != null) { modificationGroups ??= new List <IProteoformModificationGroup>(); modificationGroups.Add(new TagGroupModification(delta, item.Name, item.Members.Select(x => new TagGroupModificationMember(x.ZeroBasedStartIndex, x.ZeroBasedEndIndex, x.Weight)))); } } } // Debating about doing this as a decorators around Residues. Starting with just keeping this as another mod type. if (term.GlobalModifications?.Count > 0) { foreach (var item in term.GlobalModifications) { IProteoformMassDelta?delta = this.GetModification(item.Descriptors, modificationLookup, "Multiple global modification descriptors on same tag."); if (delta != null) { globalModifications ??= new List <IProteoformGlobalModification>(); globalModifications.Add(new GlobalModification(delta, item.TargetAminoAcids)); } } } return(new ProteoformGroup(residues, nTerminalModification, cTerminalModification, localizedModifications, unlocalizedModifications, modificationGroups, globalModifications, _water)); }
public void MultipleModsOneSite() { var modificationLookup = new CompositeModificationLookup(new IProteoformModificationLookup[] { new IgnoreKeyModificationLookup(ProFormaKey.Mass), new IgnoreKeyModificationLookup(ProFormaKey.Info), new BrnoModificationLookup(_elementProvider), _residLookup }); // Modifications have same chemical formula ... OK var term = new ProFormaTerm("SEQVKENCE", tags: new List <ProFormaTag> { new ProFormaTag(4, new[] { this.CreateBrnoDescriptor("ph"), new ProFormaDescriptor(ProFormaKey.Identifier, ProFormaEvidenceType.Resid, "AA0038") }) }); var proteoform = _factory.CreateProteoformGroup(term, modificationLookup); Assert.IsNotNull(proteoform.LocalizedModifications); Assert.AreEqual(1, proteoform.LocalizedModifications.Count); Assert.AreEqual(4, ((IProteoformLocalizedModification)proteoform.LocalizedModifications.Single()).ZeroBasedStartIndex); // Modifications have different chemical formulas ... throw! term = new ProFormaTerm("SEQVKENCE", tags: new List <ProFormaTag> { new ProFormaTag(4, new[] { this.CreateBrnoDescriptor("me1"), this.CreateBrnoDescriptor("ac") }) }); Assert.Throws <ProteoformGroupCreateException>(() => _factory.CreateProteoformGroup(term, modificationLookup)); // What about different mods at different indexes? term = new ProFormaTerm("SEQVKENCE", tags: new List <ProFormaTag> { new ProFormaTag(4, new[] { this.CreateBrnoDescriptor("ac") }), new ProFormaTag(7, new[] { this.CreateBrnoDescriptor("me1"), }) }); proteoform = _factory.CreateProteoformGroup(term, modificationLookup); Assert.IsNotNull(proteoform.LocalizedModifications); Assert.AreEqual(2, proteoform.LocalizedModifications.Count); // What about descriptors that don't have chemical formulas? term = new ProFormaTerm("SEQVKENCE", tags: new List <ProFormaTag> { new ProFormaTag(7, new[] { this.CreateBrnoDescriptor("me1"), new ProFormaDescriptor(ProFormaKey.Info, "hello!") }) }); proteoform = _factory.CreateProteoformGroup(term, modificationLookup); Assert.IsNotNull(proteoform.LocalizedModifications); Assert.AreEqual(1, proteoform.LocalizedModifications.Count); Assert.AreEqual(7, ((IProteoformLocalizedModification)proteoform.LocalizedModifications.Single()).ZeroBasedStartIndex); // Multiple N terminal mods. term = new ProFormaTerm("SEQVKENCE", null, new[] { this.CreateBrnoDescriptor("ph"), new ProFormaDescriptor(ProFormaKey.Identifier, ProFormaEvidenceType.Resid, "AA0038") }, null, null ); proteoform = _factory.CreateProteoformGroup(term, modificationLookup); Assert.IsNull(proteoform.LocalizedModifications); Assert.IsNotNull(proteoform.NTerminalModification); term = new ProFormaTerm("SEQVKENCE", null, new[] { this.CreateBrnoDescriptor("me1"), this.CreateBrnoDescriptor("ac") }, null, null ); Assert.Throws <ProteoformGroupCreateException>(() => _factory.CreateProteoformGroup(term, modificationLookup)); // Multiple C terminal mods. term = new ProFormaTerm("SEQVKENCE", null, null, new[] { this.CreateBrnoDescriptor("ph"), new ProFormaDescriptor(ProFormaKey.Identifier, ProFormaEvidenceType.Resid, "AA0038") }, null ); proteoform = _factory.CreateProteoformGroup(term, modificationLookup); Assert.IsNull(proteoform.LocalizedModifications); Assert.IsNotNull(proteoform.CTerminalModification); term = new ProFormaTerm("SEQVKENCE", null, null, new[] { this.CreateBrnoDescriptor("me1"), this.CreateBrnoDescriptor("ac") }, null ); Assert.Throws <ProteoformGroupCreateException>(() => _factory.CreateProteoformGroup(term, modificationLookup)); }