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);
        }
Esempio n. 2
0
        /// <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));
        }
Esempio n. 3
0
        /// <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);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        /// <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);
        }
Esempio n. 6
0
        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.");
        }