Beispiel #1
0
        public void TestNullArguments()
        {
            ChemicalFormula     formulaA = new ChemicalFormula("CO");
            IHasChemicalFormula ok       = null;

            Assert.AreEqual("item", Assert.Throws <ArgumentNullException>(() => { formulaA.Add(ok); }).ParamName);
            ChemicalFormula ok2 = null;

            Assert.AreEqual("formula", Assert.Throws <ArgumentNullException>(() => { formulaA.Add(ok2); }).ParamName);
            Assert.AreEqual("other", Assert.Throws <ArgumentNullException>(() => { new ChemicalFormula(ok2); }).ParamName);
            Element ok3 = null;

            Assert.AreEqual("element", Assert.Throws <ArgumentNullException>(() => { formulaA.AddPrincipalIsotopesOf(ok3, 0); }).ParamName);
            Assert.AreEqual("item", Assert.Throws <ArgumentNullException>(() => { formulaA.Remove(ok); }).ParamName);
            Assert.AreEqual("formula", Assert.Throws <ArgumentNullException>(() => { formulaA.Remove(ok2); }).ParamName);
            Assert.AreEqual("formula", Assert.Throws <ArgumentNullException>(() => { formulaA.IsSubsetOf(ok2); }).ParamName);
            Assert.AreEqual("formula", Assert.Throws <ArgumentNullException>(() => { formulaA.IsSupersetOf(ok2); }).ParamName);
            Assert.AreEqual("element", Assert.Throws <ArgumentNullException>(() => { formulaA.CountWithIsotopes(ok3); }).ParamName);
            Assert.AreEqual("element", Assert.Throws <ArgumentNullException>(() => { formulaA.CountSpecificIsotopes(ok3, 0); }).ParamName);
            Assert.IsFalse(formulaA.Equals(ok2));
            IEnumerable <IHasChemicalFormula> ok4 = null;

            Assert.AreEqual("formulas", Assert.Throws <ArgumentNullException>(() => { ChemicalFormula.Combine(ok4); }).ParamName);
            Assert.AreEqual("element", Assert.Throws <ArgumentNullException>(() => { PeriodicTable.Add(ok3); }).ParamName);

            Assert.AreEqual("formula", Assert.Throws <ArgumentNullException>(() => { new IsotopicDistribution(ok2); }).ParamName);

            IHasMass ok5 = null;

            Assert.AreEqual("objectWithMass", Assert.Throws <ArgumentNullException>(() => { ok5.ToMZ(0); }).ParamName);

            var ok7 = new PhysicalObjectWithChemicalFormula("C");
        }
Beispiel #2
0
        /// <summary>
        /// Basic overview of how chemical formulas can be used and modified
        /// </summary>
        private static void ChemicalFormulaExamples()
        {
            Console.WriteLine("**Chemical Formula Examples**");

            // Simple chemical formula creation
            ChemicalFormula formula1 = new ChemicalFormula("C2H3NO");
            WriteFormulaToConsole(formula1);

            // Input order does not matter
            ChemicalFormula formula2 = new ChemicalFormula("NH3C2O");
            WriteFormulaToConsole(formula2);

            // Formulas are identicial if they have the exact same type of elements and count
            Console.WriteLine("Are {0} and {1} equivalent? {2}", formula1, formula2, formula1.Equals(formula2));

            // You can modify exisiting chemical formulas in many ways.
            // You can add a chemical formula to a chemical formula
            formula1.Add(formula2);
            WriteFormulaToConsole(formula1);
            Console.WriteLine("Are {0} and {1} equivalent? {2}", formula1, formula2, formula1.Equals(formula2));

            // You can completely remove an element from a chemical formula
            formula1.Remove("C");
            WriteFormulaToConsole(formula1);

            // Even negative values are possible if not physically possible
            formula1.Remove(formula2);
            WriteFormulaToConsole(formula1);

            // Implicit arithmetic is also possible (supports +, -, and *)
            ChemicalFormula formula3 = formula2 - formula1;
            WriteFormulaToConsole(formula3);
            ChemicalFormula formula4 = formula3 + formula1;
            WriteFormulaToConsole(formula4);
            ChemicalFormula formula5 = formula2*5;
            WriteFormulaToConsole(formula5);

            // Formulas consist of a dictionary of isotopes and count, and by default, the most common (abundant) isotope of an element
            // is included (i.e. Carbon 12 instead of Carbon 13). You can explicitly state that you want another isotope in a chemical formula
            // by this notation: <Element Symbol>{<Mass Number>} (e.g. C{13}, N{15}, etc..)

            formula1 = new ChemicalFormula("C2C{13}2H3NO");
            formula2 = new ChemicalFormula("C4H3NO");

            WriteFormulaToConsole(formula1);
            WriteFormulaToConsole(formula2);

            Console.WriteLine("Are {0} and {1} equivalent? {2}", formula1, formula2, formula1.Equals(formula2));

            // No need to specify the mass number of the most abundant isotope for an element
            formula3 = new ChemicalFormula("C{12}2C2H3NO");
            formula4 = new ChemicalFormula("C4H3NO");
            Console.WriteLine("Are {0} and {1} equivalent? {2}", formula3, formula4, formula3.Equals(formula4));
        }
Beispiel #3
0
        public void RemoveIsotopeFromFromulaEquality()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2H3O");

            formulaA.Remove("N", 1);

            Assert.AreEqual(formulaB, formulaA);
        }
Beispiel #4
0
        public void RemoveEmptyFormulaFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2H3NO");

            formulaA.Remove(new ChemicalFormula());

            Assert.AreEqual(formulaA, formulaB);
        }
Beispiel #5
0
        public void TestRemoveObjectFromChemicalFormula()
        {
            ChemicalFormula formulaB = new ChemicalFormula("CO");
            var             ok       = new PhysicalObjectWithChemicalFormula("C");

            formulaB.Remove(ok);

            Assert.AreEqual("O", formulaB.Formula);
        }
Beispiel #6
0
        public static void RemoveElementFromFromula()
        {
            ChemicalFormula formulaA = ChemicalFormula.ParseFormula("C2H3NO");
            ChemicalFormula formulaB = ChemicalFormula.ParseFormula("C2HNO");

            formulaA.Remove(PeriodicTable.GetElement("H"), 2);

            Assert.AreEqual(formulaA, formulaB);
        }
        public void RemoveNullIsotopeFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2H3NO");

            formulaA.Remove(NullIsotope);

            Assert.AreEqual(formulaA, formulaB);
        }
        public void RemoveElementCompletelyFromFromulaWithHeavyIsotope()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2C{13}H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("H3NO");

            formulaA.Remove(PeriodicTable.GetElement("C"));

            Assert.AreEqual(formulaA, formulaB);
        }
        public void RemoveElementCompletelyFromFromulaBySymbol()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2NO");

            formulaA.Remove("H");

            Assert.AreEqual(formulaA, formulaB);
        }
        public void RemoveElementCompletelyFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2NO");

            formulaA.Remove(PeriodicTable.GetElement("H"));

            Assert.AreEqual(formulaA, formulaB);
        }
Beispiel #11
0
        public void RemoveZeroIsotopeFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2H3NO");

            formulaA.Remove(PeriodicTable.GetElement("H")[1], 0);

            Assert.AreEqual(formulaA, formulaB);
        }
Beispiel #12
0
        public void RemoveNegativeElementFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2H5NO");

            formulaA.Remove(PeriodicTable.GetElement("H"), -2);

            Assert.AreEqual(formulaA, formulaB);
        }
Beispiel #13
0
        public void RemoveFormulaFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H5NOO{16}");
            ChemicalFormula formulaB = new ChemicalFormula("H2O{16}");
            ChemicalFormula formulaC = new ChemicalFormula("C2H3NO");

            formulaA.Remove(formulaB);

            Assert.AreEqual(formulaA, formulaC);
        }
Beispiel #14
0
        public void RemoveNonExistantIsotopeFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H5NO2");
            ChemicalFormula formulaB = new ChemicalFormula("Fe");
            ChemicalFormula formulaC = new ChemicalFormula("C2H5Fe-1NO2");

            formulaA.Remove(formulaB);

            Assert.AreEqual(formulaA, formulaC);
        }
Beispiel #15
0
 /// <summary>
 /// Subtract the mass of a proton for every formal charge on a modification.
 /// </summary>
 /// <param name="_monoisotopicMass"></param>
 /// <param name="_chemicalFormula"></param>
 /// <param name="_databaseReference"></param>
 /// <param name="formalChargesDictionary"></param>
 /// <returns></returns>
 private static double AdjustMonoIsotopicMassForFormalCharge(double?_monoisotopicMass, ChemicalFormula _chemicalFormula, Dictionary <string, IList <string> > _databaseReference, Dictionary <string, int> formalChargesDictionary)
 {
     foreach (var dbAndAccession in _databaseReference.SelectMany(b => b.Value.Select(c => b.Key + "; " + c)))
     {
         if (formalChargesDictionary.ContainsKey(dbAndAccession))
         {
             if (_monoisotopicMass.HasValue)
             {
                 _monoisotopicMass -= formalChargesDictionary[dbAndAccession] * Constants.ProtonMass;
             }
             if (_chemicalFormula != null)
             {
                 _chemicalFormula.Remove(PeriodicTable.GetElement("H"), formalChargesDictionary[dbAndAccession]);
             }
             break;
         }
     }
     return((double)_monoisotopicMass);
 }
        public void RemoveZeroIsotopeFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2H3NO");

            formulaA.Remove(Element.PeriodicTable["H"][1], 0);

            Assert.AreEqual(formulaA, formulaB);
        }
        public void RemoveNullIsotopeFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2H3NO");

            formulaA.Remove(NullIsotope);

            Assert.AreEqual(formulaA, formulaB);
        }
        public void RemoveNonExistantIsotopeFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H5NO2");
            ChemicalFormula formulaB = new ChemicalFormula("Fe");
            ChemicalFormula formulaC = new ChemicalFormula("C2H5Fe-1NO2");

            formulaA.Remove(formulaB);

            Assert.AreEqual(formulaA, formulaC);
        }
        public void RemoveIsotopeFromFromulaEquality()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2H3O");

            formulaA.Remove("N", 1);

            Assert.AreEqual(formulaA, formulaB);
        }
        public void RemoveFormulaFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H5NO2");
            ChemicalFormula formulaB = new ChemicalFormula("H2O");
            ChemicalFormula formulaC = new ChemicalFormula("C2H3NO");

            formulaA.Remove(formulaB);

            Assert.AreEqual(formulaA, formulaC);
        }
        public void RemoveEmptyFormulaFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2H3NO");

            formulaA.Remove(EmptyFormula);

            Assert.AreEqual(formulaA, formulaB);
        }
        public void RemoveElementCompletelyFromFromulaWithHeavyIsotope()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2C{13}H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("H3NO");

            formulaA.Remove(Element.PeriodicTable["C"]);

            Assert.AreEqual(formulaA, formulaB);
        }
        public void RemoveElementCompletelyFromFromulaBySymbol()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2NO");

            formulaA.Remove("H");

            Assert.AreEqual(formulaA, formulaB);
        }
        public void RemoveElementCompletelyFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2NO");

            formulaA.Remove(Element.PeriodicTable["H"]);

            Assert.AreEqual(formulaA, formulaB);
        }
Beispiel #25
0
        /// <summary>
        /// Get a ModificationWithLocation from string representations of a modification specification. Returns null if the string representation is not recognized.
        /// </summary>
        /// <param name="specification"></param>
        /// <returns></returns>
        private static IEnumerable <Modification> ReadMod(List <string> specification, Dictionary <string, int> formalChargesDictionary)
        {
            // UniProt-specific fields
            string uniprotAC = null;
            string uniprotFT = null;

            // Other fields
            string          id     = null;
            List <string>   motifs = null;
            string          terminusLocalizationString = null;
            ChemicalFormula correctionFormula          = null;
            double?         monoisotopicMass           = null;
            var             externalDatabaseLinks      = new Dictionary <string, IList <string> >();
            List <string>   keywords = null;

            // Custom fields
            List <double> neutralLosses    = null;
            List <double> diagnosticIons   = null;
            string        modificationType = null;

            foreach (string line in specification)
            {
                if (line.Length >= 2)
                {
                    switch (line.Substring(0, 2))
                    {
                    case "ID":     // Mandatory
                        id = line.Substring(5);
                        break;

                    case "AC":     // Do not use! Only present in UniProt ptmlist
                        uniprotAC = line.Substring(5);
                        break;

                    case "FT":     // Optional
                        uniprotFT = line.Substring(5);
                        break;

                    case "TG":     // Which amino acid(s) or motifs is the modification on
                        motifs = new List <string>(line.Substring(5).TrimEnd('.').Split(new string[] { " or " }, StringSplitOptions.None));
                        break;

                    case "PP":     // Terminus localization
                        terminusLocalizationString = line.Substring(5);
                        break;

                    case "CF":     // Correction formula
                        correctionFormula = ChemicalFormula.ParseFormula(line.Substring(5).Replace(" ", string.Empty));
                        break;

                    case "MM":     // Monoisotopic mass difference. Might not precisely correspond to formula!
                    {
                        if (!double.TryParse(line.Substring(5), NumberStyles.Any, CultureInfo.InvariantCulture, out double thisMM))
                        {
                            throw new MzLibException(line.Substring(5) + " is not a valid monoisotopic mass");
                        }
                        monoisotopicMass = thisMM;
                    }
                    break;

                    case "DR":     // External database links!
                    {
                        var splitString = line.Substring(5).TrimEnd('.').Split(new string[] { "; " }, StringSplitOptions.None);
                        if (externalDatabaseLinks.TryGetValue(splitString[0], out IList <string> val))
                        {
                            val.Add(splitString[1]);
                        }
                        else
                        {
                            externalDatabaseLinks.Add(splitString[0], new List <string> {
                                    splitString[1]
                                });
                        }
                    }
                    break;

                    case "KW":     // ; Separated keywords
                    {
                        keywords = new List <string>(line.Substring(5).TrimEnd('.').Split(new string[] { "; " }, StringSplitOptions.None));
                    }
                    break;

                    // NOW CUSTOM FIELDS:

                    case "NL":     // Netural Losses. If field doesn't exist, single equal to 0
                        try
                        {
                            neutralLosses = new List <double>(line.Substring(5).Split(new string[] { " or " }, StringSplitOptions.RemoveEmptyEntries).Select(b => ChemicalFormula.ParseFormula(b).MonoisotopicMass));
                        }
                        catch (MzLibException)
                        {
                            neutralLosses = new List <double>(line.Substring(5).Split(new string[] { " or " }, StringSplitOptions.RemoveEmptyEntries).Select(b => double.Parse(b, CultureInfo.InvariantCulture)));
                        }
                        break;

                    case "DI":     // Masses of diagnostic ions. Might just be "DI"!!! If field doesn't exist, create an empty list!
                        try
                        {
                            diagnosticIons = new List <double>(line.Substring(5).Split(new string[] { " or " }, StringSplitOptions.RemoveEmptyEntries).Select(b => ChemicalFormula.ParseFormula(b).MonoisotopicMass));
                        }
                        catch (MzLibException)
                        {
                            diagnosticIons = new List <double>(line.Substring(5).Split(new string[] { " or " }, StringSplitOptions.RemoveEmptyEntries).Select(b => double.Parse(b, CultureInfo.InvariantCulture)));
                        }
                        break;

                    case "MT":     // Modification Type. If the field doesn't exist, set to the database name
                        modificationType = line.Substring(5);
                        break;

                    case "//":
                        if (id == null)
                        {
                            throw new MzLibException("id is null");
                        }
                        if ("CROSSLNK".Equals(uniprotFT))     // Ignore crosslinks
                        {
                            break;
                        }
                        if (uniprotAC != null)
                        {
                            modificationType = "UniProt";
                            externalDatabaseLinks.Add("UniProt", new List <string> {
                                uniprotAC
                            });
                        }
                        if (modificationType == null)
                        {
                            throw new MzLibException("modificationType of " + id + " is null");
                        }
                        if (!monoisotopicMass.HasValue && correctionFormula != null)
                        {
                            monoisotopicMass = correctionFormula.MonoisotopicMass;
                        }

                        foreach (var dbAndAccession in externalDatabaseLinks.SelectMany(b => b.Value.Select(c => b.Key + "; " + c)))
                        {
                            if (formalChargesDictionary.ContainsKey(dbAndAccession))
                            {
                                if (monoisotopicMass.HasValue)
                                {
                                    monoisotopicMass -= formalChargesDictionary[dbAndAccession] * Constants.protonMass;
                                }
                                if (correctionFormula != null)
                                {
                                    correctionFormula.Remove(PeriodicTable.GetElement("H"), formalChargesDictionary[dbAndAccession]);
                                }
                                break;
                            }
                        }
                        if (terminusLocalizationString == null || motifs == null)
                        {
                            yield return(new Modification(id, modificationType));
                        }
                        else if (ModificationWithLocation.terminusLocalizationTypeCodes.TryGetValue(terminusLocalizationString, out TerminusLocalization terminusLocalization))
                        {
                            foreach (var singleTarget in motifs)
                            {
                                string theMotif;
                                if (aminoAcidCodes.TryGetValue(singleTarget, out char possibleMotifChar))
                                {
                                    theMotif = possibleMotifChar.ToString();
                                }
                                else
                                {
                                    theMotif = singleTarget;
                                }
                                if (ModificationMotif.TryGetMotif(theMotif, out ModificationMotif motif))
                                {
                                    var idToUse = id;
                                    // Augment id if mulitple motifs!
                                    // Add id to keywords
                                    if (motifs.Count != 1)
                                    {
                                        if (keywords == null)
                                        {
                                            keywords = new List <string> {
                                                id
                                            }
                                        }
                                        ;
                                        else
                                        {
                                            keywords.Add(id);
                                        }
                                        idToUse += " on " + motif;
                                    }

                                    // Add the modification!

                                    if (!monoisotopicMass.HasValue)
                                    {
                                        // Return modification
                                        yield return(new ModificationWithLocation(idToUse, modificationType, motif, terminusLocalization, externalDatabaseLinks, keywords));
                                    }
                                    else
                                    {
                                        if (correctionFormula == null)
                                        {
                                            // Return modification with mass
                                            yield return(new ModificationWithMass(idToUse, modificationType, motif, terminusLocalization, monoisotopicMass.Value, externalDatabaseLinks,
                                                                                  keywords,
                                                                                  neutralLosses,
                                                                                  diagnosticIons));
                                        }
                                        else
                                        {
                                            // Return modification with complete information!
                                            yield return(new ModificationWithMassAndCf(idToUse, modificationType, motif, terminusLocalization, correctionFormula, monoisotopicMass.Value, externalDatabaseLinks, keywords,
                                                                                       neutralLosses,
                                                                                       diagnosticIons));
                                        }
                                    }
                                }
                                else
                                {
                                    throw new MzLibException("Could not get motif from " + singleTarget);
                                }
                            }
                        }
                        else
                        {
                            throw new MzLibException("Could not get modification site from " + terminusLocalizationString);
                        }
                        break;
                    }
                }
            }
        }
        public void RemoveZeroIsotopeFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2H3NO");

            formulaA.Remove(PeriodicTable.GetIsotope("H", 1), 0);

            Assert.AreEqual(formulaA, formulaB);
        }
        public void RemoveNegativeIsotopeFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2H5NO");

            formulaA.Remove(PeriodicTable.GetElement("H")[1], -2);

            Assert.AreEqual(formulaA, formulaB);
        }
        public void RemoveIsotopeCompletelyFromFromula()
        {
            ChemicalFormula formulaA = new ChemicalFormula("C2H3NO");
            ChemicalFormula formulaB = new ChemicalFormula("C2NO");

            formulaA.Remove(PeriodicTable.GetElement("H")[1]);

            Assert.AreEqual(formulaA, formulaB);
        }
Beispiel #29
0
        /// <summary>
        /// Basic overview of how chemical formulas can be used and modified
        /// </summary>
        private static void ChemicalFormulaExamples()
        {
            Console.WriteLine("**Chemical Formula Examples**");

            // Simple chemical formula creation
            ChemicalFormula formula1 = new ChemicalFormula("C2H3NO");

            WriteFormulaToConsole(formula1);


            // Input order does not matter
            ChemicalFormula formula2 = new ChemicalFormula("NH3C2O");

            WriteFormulaToConsole(formula2);

            // Formulas are identicial if they have the exact same type of elements and count
            Console.WriteLine("Are {0} and {1} equivalent? {2}", formula1, formula2, formula1.Equals(formula2));

            // You can modify exisiting chemical formulas in many ways.
            // You can add a chemical formula to a chemical formula
            formula1.Add(formula2);
            WriteFormulaToConsole(formula1);
            Console.WriteLine("Are {0} and {1} equivalent? {2}", formula1, formula2, formula1.Equals(formula2));

            // You can completely remove an element from a chemical formula
            formula1.Remove("C");
            WriteFormulaToConsole(formula1);

            // Even negative values are possible if not physically possible
            formula1.Remove(formula2);
            WriteFormulaToConsole(formula1);

            // Implicit arithmetic is also possible (supports +, -, and *)
            ChemicalFormula formula3 = formula2 - formula1;

            WriteFormulaToConsole(formula3);
            ChemicalFormula formula4 = formula3 + formula1;

            WriteFormulaToConsole(formula4);
            ChemicalFormula formula5 = formula2 * 5;

            WriteFormulaToConsole(formula5);

            // Formulas consist of a dictionary of isotopes and count, and by default, the most common (abundant) isotope of an element
            // is included (i.e. Carbon 12 instead of Carbon 13). You can explicitly state that you want another isotope in a chemical formula
            // by this notation: <Element Symbol>{<Mass Number>} (e.g. C{13}, N{15}, etc..)

            formula1 = new ChemicalFormula("C2C{13}2H3NO");
            formula2 = new ChemicalFormula("C4H3NO");


            WriteFormulaToConsole(formula1);
            WriteFormulaToConsole(formula2);

            Console.WriteLine("Are {0} and {1} equivalent? {2}", formula1, formula2, formula1.Equals(formula2));

            // No need to specify the mass number of the most abundant isotope for an element
            formula3 = new ChemicalFormula("C{12}2C2H3NO");
            formula4 = new ChemicalFormula("C4H3NO");
            Console.WriteLine("Are {0} and {1} equivalent? {2}", formula3, formula4, formula3.Equals(formula4));
        }