Пример #1
0
        /// <summary>
        /// Parses a chemical formula expressed as "[{atom}[count][spaces]]*",
        /// e.g. "C6H11ON", where supported atoms are H, O, N, C, S or P, etc.
        /// returning the total mass for the formula.
        ///
        /// The parser removes atoms and counts until it encounters a character
        /// it does not understand as being part of the chemical formula.
        /// The remainder is returned in the desc parameter.
        ///
        /// This parser will stop at the first minus sign. If you need to parse
        /// an expression that might contain a minus sign, use <see cref="ParseMassExpression"/>.
        /// </summary>
        /// <param name="desc">Input description, and remaining string after parsing</param>
        /// <returns>Total mass of formula parsed</returns>
        public double ParseMass(ref string desc)
        {
            double totalMass = 0.0;

            desc = desc.Trim();
            Molecule mol;
            Adduct   adduct;
            string   neutralFormula;

            if (IonInfo.IsFormulaWithAdduct(desc, out mol, out adduct, out neutralFormula))
            {
                totalMass += mol.Sum(p => p.Value * GetMass(p.Key));
                desc       = string.Empty; // Signal that we parsed the whole thing
                return(totalMass);
            }
            while (desc.Length > 0)
            {
                string sym      = NextSymbol(desc);
                double massAtom = GetMass(sym);

                // Stop if unrecognized atom found.
                if (massAtom == 0)
                {
                    // CONSIDER: Throw with a useful message?
                    break;
                }

                desc = desc.Substring(sym.Length);
                int endCount = 0;
                while (endCount < desc.Length && Char.IsDigit(desc[endCount]))
                {
                    endCount++;
                }

                long count = 1;
                if (endCount > 0)
                {
                    if (!long.TryParse(desc.Substring(0, endCount), out count))
                    {
                        count = long.MaxValue; // We know at this point that it should parse, so it's probably just too big
                    }
                }
                totalMass += massAtom * count;

                desc = desc.Substring(endCount).TrimStart();
            }

            return(totalMass);
        }
Пример #2
0
        /// <summary>
        /// Parses a chemical formula expressed as "[{atom}[count][spaces]]*",
        /// e.g. "C6H11ON", where supported atoms are H, O, N, C, S or P, etc.
        /// returning the total mass for the formula.
        ///
        /// The parser removes atoms and counts until it encounters a character
        /// it does not understand as being part of the chemical formula.
        /// The remainder is returned in the desc parameter.
        ///
        /// This parser will stop at the first minus sign. If you need to parse
        /// an expression that might contain a minus sign, use <see cref="ParseMassExpression"/>.
        /// </summary>
        /// <param name="desc">Input description, and remaining string after parsing</param>
        /// <param name="molReturn">Optional dictionary for returning the atoms and counts</param>
        /// <returns>Total mass of formula parsed</returns>
        public double ParseMass(ref string desc, Dictionary <string, int> molReturn = null)
        {
            double totalMass = 0.0;

            desc = desc.Trim();
            Molecule mol;
            Adduct   adduct;
            string   neutralFormula;
            Dictionary <string, int> dict = null;

            if (IonInfo.IsFormulaWithAdduct(desc, out mol, out adduct, out neutralFormula))
            {
                totalMass += mol.Sum(p => p.Value * GetMass(p.Key));
                desc       = string.Empty; // Signal that we parsed the whole thing
                if (molReturn != null)
                {
                    dict = mol.Dictionary.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
                }
            }
            else
            {
                if (molReturn != null)
                {
                    dict = new Dictionary <string, int>();
                }
                while (desc.Length > 0)
                {
                    string sym      = NextSymbol(desc);
                    double massAtom = GetMass(sym);

                    // Stop if unrecognized atom found.
                    if (massAtom == 0)
                    {
                        // CONSIDER: Throw with a useful message?
                        break;
                    }

                    desc = desc.Substring(sym.Length);
                    int endCount = 0;
                    while (endCount < desc.Length && Char.IsDigit(desc[endCount]))
                    {
                        endCount++;
                    }

                    var count = 1;
                    if (endCount > 0)
                    {
                        if (!int.TryParse(desc.Substring(0, endCount), out count))
                        {
                            count = int.MaxValue; // We know at this point that it should parse, so it's probably just too big
                        }
                    }
                    totalMass += massAtom * count;
                    if (dict != null)
                    {
                        if (dict.TryGetValue(sym, out var oldCount))
                        {
                            dict[sym] = count + oldCount;
                        }
                        else
                        {
                            dict.Add(sym, count);
                        }
                    }
                    desc = desc.Substring(endCount).TrimStart();
                }
            }

            if (molReturn != null)
            {
                foreach (var kvp in dict)
                {
                    var sym   = kvp.Key;
                    var count = kvp.Value;
                    if (molReturn.TryGetValue(sym, out var oldCount))
                    {
                        molReturn[sym] = count + oldCount;
                    }
                    else
                    {
                        molReturn.Add(sym, count);
                    }
                }
            }
            return(totalMass);
        }