public static IEnumerable <IChemicalFormula> Validate(this IEnumerable <IChemicalFormula> formulas, FilterTypes filters = FilterTypes.All) { bool useValence = filters.HasFlag(FilterTypes.Valence); bool useHydrogenCarbonRatio = filters.HasFlag(FilterTypes.HydrogenCarbonRatio); foreach (IChemicalFormula formula in formulas) { if (useHydrogenCarbonRatio) { double ratio = formula.ChemicalFormula.GetCarbonHydrogenRatio(); if (ratio < 0.5 || ratio > 2.0) { continue; } } if (useValence) { int totalValence = 0; int maxValence = 0; int oddValences = 0; int atomCount = 0; int[] isotopes = formula.ChemicalFormula.GetIsotopes(); for (int i = 0; i < isotopes.Length; i++) { int numAtoms = isotopes[i]; if (numAtoms != 0) { continue; } Isotope isotope = PeriodicTable.GetIsotope(i); int numValenceElectrons = isotope.ValenceElectrons; totalValence += numValenceElectrons * numAtoms; atomCount += numAtoms; if (numValenceElectrons > maxValence) { maxValence = numValenceElectrons; } if (numValenceElectrons % 2 != 0) { oddValences += numAtoms; } } if (!((totalValence % 2 == 0 || oddValences % 2 == 0) && (totalValence >= 2 * maxValence) && (totalValence >= ((2 * atomCount) - 1)))) { continue; } } yield return(formula); } }
/// <summary> /// Add the principal isotope of the element to this chemical formula /// given its chemical symbol /// </summary> /// <param name="symbol">The chemical symbol of the element to add</param> /// <param name="count">The number of the element to add</param> public void Add(string symbol, int count) { try { Isotope isotope = PeriodicTable.GetElement(symbol).PrincipalIsotope; Add(isotope, count); } catch (KeyNotFoundException e) { throw new KeyNotFoundException(string.Format("The element symbol '{0}' is not found in the periodic table", symbol), e); } }
/// <summary> /// Gets the unique elements in this chemical formula /// </summary> /// <returns></returns> public IEnumerable <Element> GetElements() { HashSet <Element> elements = new HashSet <Element>(); for (int i = 0; i <= _largestIsotopeId; i++) { if (_isotopes[i] != 0) { elements.Add(PeriodicTable.GetIsotope(i).Element); } } return(elements); }
/// <summary> /// Gets the total number of protons in this chemical formula /// </summary> /// <returns></returns> public int GetProtonCount() { int protons = 0; for (int i = 0; i <= _largestIsotopeId; i++) { if (_isotopes[i] == 0) { continue; } protons += PeriodicTable.GetIsotope(i).Protons *_isotopes[i]; } return(protons); }
/// <summary> /// Parses a string representation of chemical formula and adds the elements /// to this chemical formula /// </summary> /// <param name="formula">the Chemical Formula to parse</param> private void ParseString(string formula) { if (string.IsNullOrEmpty(formula)) { return; } if (!IsValidChemicalFormula(formula)) { throw new FormatException("Input string for chemical formula was in an incorrect format"); } foreach (Match match in FormulaRegex.Matches(formula)) { string chemsym = match.Groups[1].Value; // Group 1: Chemical Symbol Element element; if (PeriodicTable.TryGetElement(chemsym, out element)) { Isotope isotope = element.PrincipalIsotope; // Start with the most abundant (principal) isotope if (chemsym.Equals("D")) // Special case for Deuterium { isotope = element.Isotopes[2]; } else if (match.Groups[2].Success) // Group 2 (optional): Isotope Mass Number { isotope = element[int.Parse(match.Groups[2].Value)]; } int sign = match.Groups[3].Success ? // Group 3 (optional): Negative Sign -1 : 1; int numofelem = match.Groups[4].Success ? // Group 4 (optional): Number of Elements int.Parse(match.Groups[4].Value) : 1; Add(isotope, sign * numofelem); } else { throw new ArgumentException(string.Format("The chemical Symbol '{0}' does not exist in the Periodic Table", chemsym)); } } }
public ChemicalFormula(int[] uniqueIdCounts) { int count = uniqueIdCounts.Length; _isotopes = new int[count]; MonoisotopicMass = 0; for (int i = 0; i < count; i++) { int isotopes = uniqueIdCounts[i]; if (isotopes != 0) { _isotopes[i] = isotopes; MonoisotopicMass += isotopes * PeriodicTable.GetIsotope(i).AtomicMass; _largestIsotopeId = i; } } _isFormulaDirty = _isDirty = true; }
/// <summary> /// Recalculate parameters of the chemical formula /// </summary> private void CleanUp() { int atomCount = 0; int isotopeCount = 0; double monoMass = 0.0; double avgMass = 0.0; HashSet <int> elements = new HashSet <int>(); // Loop over every possible isotope in this formula for (int i = 0; i <= _largestIsotopeId; i++) { int count = _isotopes[i]; // Skip zero isotopes if (count == 0) { continue; } Isotope isotope = PeriodicTable.GetIsotope(i); Element element = isotope.Element; elements.Add(element.AtomicNumber); isotopeCount++; atomCount += count; monoMass += count * isotope.AtomicMass; avgMass += count * element.AverageMass; } // Set the instance variables to their new values _elementCount = elements.Count; MonoisotopicMass = monoMass; _averageMass = avgMass; _isotopeCount = isotopeCount; _atomCount = atomCount; // Mark as clean _isDirty = false; }
/// <summary> /// Produces the Hill Notation of the chemical formula /// </summary> public string GetHillNotation(string delimiter = "") { string carbonPart = string.Empty; string hydrogenPart = string.Empty; List <string> otherParts = new List <string>(); StringBuilder sb = new StringBuilder(4); bool nonNullDelimiter = !string.IsNullOrEmpty(delimiter); for (int i = 0; i <= _largestIsotopeId; i++) { int count = _isotopes[i]; if (count == 0) { continue; } Isotope isotope = PeriodicTable.GetIsotope(i); sb.Clear(); sb.Append(isotope.AtomicSymbol); if (!isotope.IsPrincipalIsotope) { sb.Append('{'); sb.Append(isotope.MassNumber); sb.Append('}'); } if (count != 1) { sb.Append(count); } switch (isotope.AtomicSymbol) { case "C": if (nonNullDelimiter && !string.IsNullOrEmpty(carbonPart)) { carbonPart += delimiter; } carbonPart += sb.ToString(); break; case "D": case "H": if (nonNullDelimiter && !string.IsNullOrEmpty(hydrogenPart)) { hydrogenPart += delimiter; } hydrogenPart += sb.ToString(); break; default: otherParts.Add(sb.ToString()); break; } } if (string.IsNullOrEmpty(carbonPart)) { // No carbons, so just add the hydrogen to the list and sort alphabetically if (!string.IsNullOrEmpty(hydrogenPart)) { otherParts.Add(hydrogenPart); } otherParts.Sort(); } else { otherParts.Sort(); if (!string.IsNullOrEmpty(hydrogenPart)) { otherParts.Insert(0, hydrogenPart); } otherParts.Insert(0, carbonPart); } return(string.Join(delimiter, otherParts)); }
public int Count(string symbol, int atomicNumber) { Isotope isotope = PeriodicTable.GetElement(symbol)[atomicNumber]; return(Count(isotope)); }
public int Count(string symbol) { Element element = PeriodicTable.GetElement(symbol); return(Count(element)); }
/// <summary> /// Remove all the isotopes of an chemical element represented by the symbol /// from this chemical formula /// </summary> /// <param name="symbol">The symbol of the chemical element to remove</param> /// <returns>True if the element was present and removed, false otherwise</returns> public int Remove(string symbol) { return(Remove(PeriodicTable.GetElement(symbol))); }
/// <summary> /// Remove the principal isotope of the element represented by the symbol /// from this chemical formula /// </summary> /// <param name="symbol">The symbol of the chemical element to remove</param> /// <param name="count">The number of isotopes to remove</param> public void Remove(string symbol, int count) { Add(PeriodicTable.GetElement(symbol).PrincipalIsotope, -count); }
public IEnumerable <ChemicalFormula> FromMass(double lowMass, double highMass, int maxNumberOfResults = int.MaxValue, bool sort = true) { if (highMass <= lowMass) { throw new ArgumentException("The high mass must be greater than the low mass"); } if (!MaximumFormula.Contains(MinimumFormula)) { throw new ArgumentException("The maximum formula must include the minimum formula"); } List <ChemicalFormula> returnFormulas = new List <ChemicalFormula>(); // The minimum formula required for any return formulas double correctedLowMass = lowMass; double correctedHighMass = highMass; bool minFormulaExists = MinimumFormula.IsotopeCount != 0; int[] minValues = null; double minFormulaMass = 0; if (minFormulaExists) { minValues = MinimumFormula.GetIsotopes(); minFormulaMass = MinimumFormula.MonoisotopicMass; correctedLowMass -= minFormulaMass; correctedHighMass -= minFormulaMass; // Add the minimum formula itself if it is within the bounds } // The maximum formula allowed, represented in number of isotopes int[] maxValues = MaximumFormula.GetIsotopes(); // The current formula represented in isotopes int[] currentFormula = new int[maxValues.Length]; // A list of all the isotopes masses double[] masses = new double[maxValues.Length]; int length = maxValues.Length; for (int j = 0; j < length; j++) { if (minFormulaExists && j < minValues.Length) { maxValues[j] -= minValues[j]; } if (maxValues[j] == 0) { continue; } masses[j] = PeriodicTable.GetIsotope(j).AtomicMass; } masses[0] = PeriodicTable.GetIsotope(0).AtomicMass; GenerateFormulaHelper(correctedLowMass, correctedHighMass, masses, maxValues, length - 1, currentFormula, returnFormulas); if (minFormulaExists) { foreach (ChemicalFormula formula in returnFormulas) { formula.Add(MinimumFormula); } if (minFormulaMass >= lowMass && minFormulaMass <= highMass) { returnFormulas.Add(new ChemicalFormula(MinimumFormula)); } } if (!sort) { return(returnFormulas); } double meanValue = (highMass + lowMass) / 2.0; return(returnFormulas.OrderBy(formula => Math.Abs(formula.MonoisotopicMass - meanValue)).Take(maxNumberOfResults)); }