private IsotopicDistribution GetDistribution(IChemicalFormula formula, double fineResolution, double minProbability, double molecularWeightResolution) { var a = GetNewFineAndMergeResolutions(fineResolution); fineResolution = a.Item1; double _mergeFineResolution = a.Item2; var elementalComposition = new List <List <Composition> >(); // Get all the unique elements that might have isotopes foreach (var elementAndCount in formula.GetElements()) { int count = elementAndCount.Count; var isotopeComposition = new List <Composition>(); foreach (Isotope isotope in elementAndCount.Entity.Isotopes.OrderBy(iso => iso.AtomicMass)) { var c = new Composition { Atoms = count, MolecularWeight = isotope.AtomicMass, Power = isotope.AtomicMass, Probability = isotope.RelativeAbundance }; isotopeComposition.Add(c); } elementalComposition.Add(isotopeComposition); } foreach (List <Composition> compositions in elementalComposition) { double sumProb = compositions.Sum(t => t.Probability); foreach (Composition composition in compositions) { composition.Probability /= sumProb; composition.LogProbability = Math.Log(composition.Probability); composition.Power = Math.Floor(composition.MolecularWeight / molecularWeightResolution + 0.5); } } IsotopicDistribution dist = CalculateFineGrain(elementalComposition, molecularWeightResolution, _mergeFineResolution, fineResolution, minProbability); // RTF: Not handling isotopes right now //double additionalMass = 0; //foreach (var isotopeAndCount in formula.Isotopes) // additionalMass += isotopeAndCount.Key.AtomicMass * isotopeAndCount.Value; //for (int i = 0; i < dist.masses.Length; i++) // dist.masses[i] += additionalMass; return(dist); }
/// <summary>Gets the chemical formula as a string in Hill notation.</summary> /// <param name="chemicalFormula">The chemical formula.</param> /// <returns></returns> public static string GetChemicalFormulaString(IChemicalFormula chemicalFormula) { // Local function for converting a single element to a string. string GetElementString(IEntityCardinality <IElement> element) { if (element.Count == 0) // Don't write zero. { return(string.Empty); } if (element.Count == 1) // If the count is 1, just use the symbol. { return(element.Entity.Symbol); } // In all other cases need to write out count too. return($"{element.Entity.Symbol}{element.Count}"); } // Main function. ICollection <IEntityCardinality <IElement> > elements = chemicalFormula.GetElements().ToList(); IList <string> elementStrings = new List <string>(); // Look for carbon first. If it exists, write it and then hydrogen. IEntityCardinality <IElement> carbon = elements.SingleOrDefault(e => e.Entity.AtomicNumber == 6); if (carbon != null && carbon.Count > 0) { elementStrings.Add(GetElementString(carbon)); elements.Remove(carbon); IEntityCardinality <IElement> hydrogen = elements.SingleOrDefault(e => e.Entity.AtomicNumber == 1); if (hydrogen != null && hydrogen.Count > 0) { elementStrings.Add(GetElementString(hydrogen)); elements.Remove(hydrogen); } } // Write out the rest in alphabetical order. foreach (IEntityCardinality <IElement> element in elements.OrderBy(e => e.Entity.Symbol)) { if (element.Count > 0) { elementStrings.Add(GetElementString(element)); } } return(string.Join("", elementStrings)); }
/// <summary> /// Indicates whether the current object is equal to another object of the same type. /// </summary> /// <param name="other">An object to compare with this object.</param> /// <returns> /// true if the current object is equal to the <paramref name="other">other</paramref> parameter; otherwise, false. /// </returns> public bool Equals(IChemicalFormula other) { if (other == null) { return(false); } if (this == other) { return(true); } IReadOnlyCollection <IEntityCardinality <IElement> > otherElements = other.GetElements(); if (_elements.Count != otherElements.Count) { return(false); } if (_elements.Sum(x => x.Count) != otherElements.Sum(x => x.Count)) { return(false); } foreach (IEntityCardinality <IElement> element in _elements) { var otherElement = otherElements.SingleOrDefault(x => x.Entity.Equals(element.Entity)); // Check that the other chemical formula has this element. if (otherElement == null) { return(false); } // Check the counts. if (element.Count != otherElement.Count) { return(false); } } return(true); }
public void IsotopeTest() { const string formula = "C(-9) 13C(9)"; var composition = UnimodComposition.CreateFromFormula(formula, atomProvider); var cardinalities = composition.GetAtomCardinalities(); Assert.AreEqual(2, cardinalities.Count); Assert.AreEqual(atomProvider.GetUnimodCompositionAtom("C"), cardinalities[0].Atom); Assert.AreEqual(-9, cardinalities[0].Count); Assert.AreEqual(atomProvider.GetUnimodCompositionAtom("13C"), cardinalities[1].Atom); Assert.AreEqual(9, cardinalities[1].Count); IChemicalFormula chemicalFormula = composition.GetChemicalFormula(); var elements = chemicalFormula.GetElements(); Assert.AreEqual(2, elements.Count); Assert.AreEqual(-9, elements.Single(x => x.Entity.Symbol == "C").Count); Assert.AreEqual(9, elements.Single(x => x.Entity.Symbol == "13C").Count); }
/// <summary> /// Adds the specified formula. /// </summary> /// <param name="otherFormula">The formula.</param> /// <returns></returns> public IChemicalFormula Add(IChemicalFormula otherFormula) { if (otherFormula == null) { return(this); } var otherElements = otherFormula.GetElements().ToList(); if (otherElements.Count == 0) { return(this); } var formula = new ChemicalFormula(); // Add everything from this formula foreach (var element in _elements) { var otherElement = otherElements.SingleOrDefault(x => x.Entity.Equals(element.Entity)); if (otherElement == null) { formula._elements.Add(element); } else { formula._elements.Add(new EntityCardinality <IElement>(element.Entity, element.Count + otherElement.Count)); otherElements.Remove(otherElement); } } // Add unique things from other formula foreach (var otherElement in otherElements) { formula._elements.Add(otherElement); } return(formula); }
private IIsotopicDistribution Mercury(IChemicalFormula cf, double limit) { // Build up the molecular super atom (MSA) until it is the entire molecule // A "molecular super atom" refers to a fictitious chemical compound whose // formula is a partial composition of the target compound. double[]? msaMz = null; double[]? msaAbundance = null; double[]? tmpMz = null; double[]? tmpAbundance = null; bool msaInitialized = false; foreach (IEntityCardinality <IElement> kvp in cf.GetElements()) { uint n = (uint)kvp.Count; if (n == 0) { continue; } int isotopeCount = kvp.Entity.Isotopes.Count; double[] esaMz = new double[isotopeCount]; double[] esaAbundance = new double[isotopeCount]; int i = 0; foreach (var iso in kvp.Entity.Isotopes.OrderBy(x => x.AtomicMass)) // Algorithm requires it to be sorted. { esaMz[i] = iso.AtomicMass; esaAbundance[i] = iso.RelativeAbundance; i++; } while (true) { // This is an implicit FFT that decomposes the number of a particular element // into the sum of its powers of 2. // Check if we need to do the MSA update - only if n is odd if ((n & 1) == 1) { // MSA update if (msaInitialized) { // normal update Convolve(ref tmpMz, ref tmpAbundance, msaMz, msaAbundance, esaMz, esaAbundance); msaMz = this.CopyArray(tmpMz); msaAbundance = this.CopyArray(tmpAbundance); } else { // for first assignment, MSA = ESA msaMz = this.CopyArray(esaMz); msaAbundance = this.CopyArray(esaAbundance); msaInitialized = true; } Prune(ref msaMz, ref msaAbundance, limit); } // The ESA update is always carried out (with the exception of the last time, i.e., when n == 1) if (n == 1) { break; } Convolve(ref tmpMz, ref tmpAbundance, esaMz, esaAbundance, esaMz, esaAbundance); esaMz = this.CopyArray(tmpMz); esaAbundance = this.CopyArray(tmpAbundance); Prune(ref esaMz, ref esaAbundance, limit); n = n >> 1; } } if (msaMz != null && msaAbundance != null) { return(new IsotopicDistribution(msaMz, msaAbundance)); } throw new Exception("Couldn't create masses or abundances."); }