Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mzLib/Chemistry/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,7 @@ public static class Constants
internal const int CarbonAtomicNumber = 6;

internal const int HydrogenAtomicNumber = 1;

public static readonly ChemicalFormula WaterChemicalFormula = ChemicalFormula.ParseFormula("H2O");
}
}
18 changes: 8 additions & 10 deletions mzLib/Omics/Modifications/Modification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Omics.Modifications
/// Represents a modification
/// Mods.txt format was taken from https://ftp.uniprot.org/pub/databases/uniprot/current_release/knowledgebase/complete/docs/ptmlist.txt
/// </summary>
public class Modification : IComparable<Modification>
public class Modification : IComparable<Modification>, IHasChemicalFormula
{
public string IdWithMotif { get; protected set; }
public string OriginalId { get; protected set; }
Expand All @@ -18,18 +18,12 @@ public class Modification : IComparable<Modification>
public ModificationMotif Target { get; protected set; }
public string LocationRestriction { get; protected set; }
public ChemicalFormula ChemicalFormula { get; protected set; }
private double? monoisotopicMass = null;
private readonly double? _monoisotopicMass = null;

public double? MonoisotopicMass
{
get
{
return ClassExtensions.RoundedDouble(monoisotopicMass);
}
private set
{
monoisotopicMass = value;
}
get => _monoisotopicMass.RoundedDouble();
private init => _monoisotopicMass = value;
}

public Dictionary<string, IList<string>> DatabaseReference { get; protected set; }
Expand Down Expand Up @@ -313,5 +307,9 @@ public int CompareTo(Modification? other)

return Nullable.Compare(this.MonoisotopicMass, other.MonoisotopicMass);
}

// IHasChemicalFormula Implementations.
double IHasMass.MonoisotopicMass => MonoisotopicMass.Value;
public ChemicalFormula ThisChemicalFormula => this.ChemicalFormula;
}
}
2 changes: 1 addition & 1 deletion mzLib/Proteomics/AminoAcidPolymer/AminoAcidPolymer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ public int ElementCountWithIsotopes(string element)
if (_modifications != null)
count += _modifications.Where(mod => mod is IHasChemicalFormula).Cast<IHasChemicalFormula>().Sum(mod => mod.ThisChemicalFormula.CountWithIsotopes(element));

count += ChemicalFormula.ParseFormula("H2O").CountWithIsotopes(element);
count += Constants.WaterChemicalFormula.CountWithIsotopes(element);
return count;
}

Expand Down
83 changes: 83 additions & 0 deletions mzLib/Test/Transcriptomics/ModomicsLoaderTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Chemistry;
using NUnit.Framework;
using NUnit.Framework.Legacy;
using UsefulProteomicsDatabases.Transcriptomics;

namespace Test.Transcriptomics
{
[TestFixture]
public class ModomicsLoaderTests
{
[Test]
public void LoadModomics_ParsesEntriesCorrectly()
{
// Adjust resource name to match your project/namespace
var resourceName = "UsefulProteomicsDatabases.Transcriptomics.modomics.json";

var mods = ModomicsLoader.LoadModomics();

Assert.That(mods, Is.Not.Empty);
Assert.That(mods.All(m => !string.IsNullOrWhiteSpace(m.IdWithMotif)), Is.True);
Assert.That(mods.All(m => m.IdWithMotif.Contains(" on ")), Is.True);
}

[Test]
public void LoadModomics_SkipsUnknownBases()
{
var mods = ModomicsLoader.LoadModomics();

// Should skip modifications with unknown bases (e.g. "X")
Assert.That(mods.Any(m => m.IdWithMotif.Contains("on X")), Is.False);
}

[Test]
public void LoadModomics_CachesResults()
{
var firstLoad = ModomicsLoader.LoadModomics();
var secondLoad = ModomicsLoader.LoadModomics();
Assert.That(ReferenceEquals(firstLoad, secondLoad), Is.True);
}

[Test]
public static void MethylsHaveCorrectFormula()
{
var mods = ModomicsLoader.LoadModomics()
.Where(p => !p.ModificationType.Contains("Cap"))
.ToList();

var singleMethylMods = mods.Where(m =>
System.Text.RegularExpressions.Regex.IsMatch(
m.IdWithMotif,
@"^m\d+[ACGU] on [ACGU]$"))
.ToList();

// Exception to normal CH2 formula rule
var m3C = singleMethylMods.FirstOrDefault(m => m.IdWithMotif.StartsWith("m3C on C"));
Assert.That(m3C, Is.Not.Null, "Expected to find m3C modification");
Assert.That(m3C.ChemicalFormula.Equals(ChemicalFormula.ParseFormula("C1H3")), Is.True, "m3C should have formula C1H3");
singleMethylMods.Remove(m3C);

var expectedFormula = ChemicalFormula.ParseFormula("C1H2");
CollectionAssert.AreEqual(
Enumerable.Repeat(expectedFormula, singleMethylMods.Count),
singleMethylMods.Select(p => p.ChemicalFormula)
);

var diMethylMods = mods.Where(m =>
System.Text.RegularExpressions.Regex.IsMatch(
m.IdWithMotif,
@"^m\d+[ACGU]m on [ACGU]$"))
.ToList();

expectedFormula = ChemicalFormula.ParseFormula("C2H4");
CollectionAssert.AreEqual(
Enumerable.Repeat(expectedFormula, diMethylMods.Count).ToList(),
diMethylMods.Select(p => p.ChemicalFormula).ToList()
);
}
}
}
2 changes: 1 addition & 1 deletion mzLib/Transcriptomics/Nucleotide.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class Nucleotide : INucleotide, IEquatable<Nucleotide>
/// <summary>
/// A dictionary of all known residues, can be searched via one letter, three letter, or the name of the residue
/// </summary>
internal static readonly Dictionary<string, Nucleotide> AllKnownResidues;
public static readonly Dictionary<string, Nucleotide> AllKnownResidues;

internal static readonly Nucleotide[] ResiduesByLetter;

Expand Down
Loading
Loading