Exemplo n.º 1
0
        /// <summary>
        /// Decides wheter to use the round robin algorithm or full enumeration algorithm.
        /// The round robin implementation here is optimized for chemical elements in organic compounds. It gets slow
        /// if
        /// - the mass of the smallest element is very large (i.e. hydrogen is not allowed)
        /// - the maximal mass to decompose is too large (round robin always decomposes integers. Therefore, the mass have
        ///   to be small enough to be represented as 32 bit integer)
        /// - the number of elements in the set is extremely small (in this case, however, the problem becomes trivial anyways)
        ///
        /// In theory we could handle these problems by optimizing the way DECOMP discretizes the masses. However, it's easier
        /// to just fall back to the full enumeration method if a problem occurs (especially, because most of the problems
        /// lead to trivial cases that are fast to compute).
        /// </summary>
        /// <returns>true if the problem is ill-posed (i.e. should be calculated by full enumeration method)</returns>
        private static bool IsIllPosed(double minMass, double maxMass, MolecularFormulaRange mfRange)
        {
            // when the number of integers to decompose is incredible large
            // we have to adjust the internal settings (e.g. precision!)
            // instead we simply fallback to the full enumeration method
            if (maxMass - minMass >= 1)
            {
                return(true);
            }
            if (maxMass > 400000)
            {
                return(true);
            }
            // if the number of elements to decompose is very small
            // we fall back to the full enumeration methods as the
            // minimal decomposable mass of a certain residue class might
            // exceed the 32 bit integer space
            if (mfRange.GetIsotopes().Count() <= 2)
            {
                return(true);
            }

            // if the mass of the smallest element in alphabet is large
            // it is more efficient to use the full enumeration method
            double smallestMass = double.PositiveInfinity;

            foreach (IIsotope i in mfRange.GetIsotopes())
            {
                smallestMass = Math.Min(smallestMass, i.ExactMass.Value);
            }

            return(smallestMass > 5);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Checks if input parameters are valid and throws an <see cref="ArgumentOutOfRangeException"/> otherwise.
        /// </summary>
        private static void CheckInputParameters(IChemObjectBuilder builder,
                                                 double minMass, double maxMass,
                                                 MolecularFormulaRange mfRange)
        {
            if (minMass < 0.0)
            {
                throw new ArgumentOutOfRangeException(nameof(minMass), "The minimum mass values must be >=0");
            }
            if (maxMass < 0.0)
            {
                throw new ArgumentOutOfRangeException(nameof(maxMass), "The maximum mass values must be >=0");
            }
            if ((minMass > maxMass))
            {
                throw (new ArgumentException("Minimum mass must be <= maximum mass"));
            }

            if ((mfRange == null) || (mfRange.GetIsotopes().Count() == 0))
            {
                throw (new ArgumentException("The MolecularFormulaRange parameter must be non-null and must contain at least one isotope"));
            }

            // Sort the elements by mass in ascending order. That speeds up
            // the search.
            foreach (IIsotope isotope in mfRange.GetIsotopes())
            {
                // Check if exact mass of each isotope is set
                if (isotope.ExactMass == null)
                {
                    throw new ArgumentException(
                              "The exact mass value of isotope " + isotope
                              + " is not set");
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Initiate the MolecularFormulaGenerator.
        /// </summary>
        /// <param name="minMass">Lower boundary of the target mass range</param>
        /// <param name="maxMass">Upper boundary of the target mass range</param>
        /// <param name="mfRange">A range of elemental compositions defining the search space</param>
        /// <exception cref="ArgumentOutOfRangeException">In case some of the isotopes in mfRange has undefined exact mass or in case illegal parameters are provided (e.g., negative mass values or empty MolecularFormulaRange)</exception>
        /// <seealso cref="MolecularFormulaRange"/>
        internal RoundRobinFormulaGenerator(IChemObjectBuilder builder,
                                            double minMass, double maxMass,
                                            MolecularFormulaRange mfRange)
        {
            this.builder = builder;
            var isotopes = new List <IIsotope>(mfRange.GetIsotopes().Count());

            foreach (IIsotope iso in mfRange.GetIsotopes())
            {
                if (mfRange.GetIsotopeCountMin(iso) >= 0 && mfRange.GetIsotopeCountMax(iso) > 0)
                {
                    isotopes.Add(iso);
                }
            }
            this.decomposer = DecomposerFactory.Instance.GetDecomposerFor(isotopes.ToArray()).DecomposeIterator(minMass, maxMass, mfRange);
            this.done       = false;
            this.mfRange    = mfRange;
        }
Exemplo n.º 4
0
        public void TestIsotopes()
        {
            MolecularFormulaRange mfRange = new MolecularFormulaRange();

            mfRange.AddIsotope(builder.NewIsotope("C"), 0, 10);
            mfRange.AddIsotope(builder.NewIsotope("F"), 0, 10);

            IEnumerator <IIsotope> istoIter = mfRange.GetIsotopes().GetEnumerator();
            int counter = 0;

            while (istoIter.MoveNext())
            {
                counter++;
            }
            Assert.AreEqual(2, counter);
        }
        /// <summary>
        /// Initiate the MolecularFormulaGenerator.
        /// </summary>
        /// <param name="minMass">Lower boundary of the target mass range</param>
        /// <param name="maxMass">Upper boundary of the target mass range</param>
        /// <param name="mfRange">A range of elemental compositions defining the search space</param>
        /// <exception cref="ArgumentOutOfRangeException">In case some of the isotopes in mfRange has undefined exact mass or in case illegal parameters are provided (e.g.,             negative mass values or empty MolecularFormulaRange)</exception>
        /// <seealso cref="MolecularFormulaRange"/>
        public FullEnumerationFormulaGenerator(IChemObjectBuilder builder,
                                               double minMass, double maxMass,
                                               MolecularFormulaRange mfRange)
        {
            Trace.TraceInformation("Initiate MolecularFormulaGenerator, mass range " + minMass + "-" + maxMass);

            // Check parameter values
            if (minMass < 0.0)
            {
                throw (new ArgumentOutOfRangeException(nameof(minMass), "The minimum and maximum mass values must be >=0"));
            }
            if (maxMass < 0.0)
            {
                throw (new ArgumentOutOfRangeException(nameof(maxMass), "The minimum and maximum mass values must be >=0"));
            }

            if ((minMass > maxMass))
            {
                throw (new ArgumentException("Minimum mass must be <= maximum mass"));
            }

            if ((mfRange == null) || (mfRange.GetIsotopes().Count() == 0))
            {
                throw (new ArgumentException("The MolecularFormulaRange parameter must be non-null and must contain at least one isotope"));
            }

            // Save the parameters
            this.builder = builder;
            this.minMass = minMass;
            this.maxMass = maxMass;

            // Sort the elements by mass in ascending order. That speeds up
            // the search.
            var isotopesSet = new SortedSet <IIsotope>(
                new IIsotopeSorterByMass());

            foreach (IIsotope isotope in mfRange.GetIsotopes())
            {
                // Check if exact mass of each isotope is set
                if (isotope.ExactMass == null)
                {
                    throw new ArgumentException($"The exact mass value of isotope {isotope} is not set");
                }
                isotopesSet.Add(isotope);
            }
            isotopes = isotopesSet.ToArray();

            // Save the element counts from the provided MolecularFormulaRange
            minCounts = new int[isotopes.Length];
            maxCounts = new int[isotopes.Length];
            for (int i = 0; i < isotopes.Length; i++)
            {
                minCounts[i] = mfRange.GetIsotopeCountMin(isotopes[i]);
                maxCounts[i] = mfRange.GetIsotopeCountMax(isotopes[i]);

                // Update the maximum count according to the mass limit
                int maxCountAccordingToMass = (int)Math.Floor(maxMass
                                                              / isotopes[i].ExactMass.Value);
                if (maxCounts[i] > maxCountAccordingToMass)
                {
                    maxCounts[i] = maxCountAccordingToMass;
                }
            }

            // Set the current counters to minimal values, initially
            currentCounts = Arrays.CopyOf(minCounts, minCounts.Length);
        }