public DatabaseSearcherThreadLocalStorage(bool minimize_memory_usage, int psms_length)
        {
            this.num_target_peptides = 0;
            this.num_decoy_peptides = 0;
            this.proteins = 0;

            if (!minimize_memory_usage)
                this.peptides_observed = new Dictionary<FastSubstring, bool>(new LeucineSequenceEqualityComparer());
            else
                this.peptides_observed = null;

            digested_peptides_buf = new FastListOfBoxes<Peptide>(1000);
            modified_peptides_buf = new FastListOfBoxes<Peptide>(1000);
            fixed_modifications_buf = new Dictionary<int, List<Modification>>(1000);
            possible_modifications_buf = new Dictionary<int, List<Modification>>(1000);
            mass_spectra_indices_buf = new List<int>(1000);
            product_masses_buf = new double[1000];
            fast_q_sorter = new FastQSorter();
            psm = new PeptideSpectrumMatch();
            psms = new PeptideSpectrumMatch[psms_length];
        }
Ejemplo n.º 2
0
        // This method is called, via PeptideSpectrumMatch.ScoreMatch, in a
        // tight loop in DatabaseSearcher.DoSearch. Originally, (i) a
        // List<Double> containing the product masses was newly allocated and
        // returned each time this method was called, and then (ii)
        // PeptideSpectrumMatch.ScoreMatch converted this List<Double> to an
        // array of doubles. Thus, a lot of garbage was generated and needed to
        // be collected.
        //
        // In the current version of this function, we instead take a
        // preallocated array, product_masses_buf, by reference, and we fill in
        // the beginning of this array with the calculated product masses. If
        // product_masses_buf to small to store the calculated product masses,
        // we resize it so it is big enough. If product_masses_buf is bigger
        // than necessary, we only fill in the beginning of it and leave the
        // rest of the entries unchanged (in case the extra capacity is needed
        // on subsequent calls). We return the total number of entries in the
        // product_masses_buf that are actually used.
        //
        // It is important to emphasize that, in general,
        // product_masses_buf.Length != the number of calculated product
        // masses. That is, the number of elements in the array does not equal
        // the number of elements that are filled in with meaningful info.
        //
        // Note also that the fast_q_sorter object's internal state will be
        // modified by this method.
        public int CalculateProductMasses(ProductType[] productTypes, ref double[] product_masses_buf, FastQSorter fast_q_sorter)
        {
            // If product_masses isn't big enough to store all the product
            // masses we might want to store, resize it.
            int max_products = 2 * (Length - 1);
            if(product_masses_buf.Length < max_products)
            {
                System.Array.Resize<double>(ref product_masses_buf, max_products);
            }

            // Calculate the product masses and store them in the prefix of
            // product_masses_buf.
            int i = 0;
            for(int r = 1; r < Length; r++)
            {
                for(int p = 0; p < productTypes.Length; p++)
                {
                    if(!(productTypes[p] == ProductType.c && r < Length && this[r] == 'P') &&
                       !(productTypes[p] == ProductType.zdot && Length - r < Length && this[Length - r] == 'P'))
                    {
                        double product_mass = CalculateProductMass(productTypes[p], r);
                        product_masses_buf[i] = product_mass;
                        ++i;
                    }
                }
            }
            int total_products = i;

            // Sort the product masses. Only the filled-in prefix of
            // product_masses_buf is sorted.
            fast_q_sorter.Sort(product_masses_buf, 0, total_products);

            // Return the number of products, i.e., the size of the filled-in
            // prefix of product_masses_buf.
            return total_products;
        }
        // Calculates the score for this match. Both product_masses_buf and
        // fast_q_sorter are modified by this method; see Init's documentation
        // for details.
        private void ScoreMatch(MassTolerance productMassTolerance, ref double[] product_masses_buf, FastQSorter fast_q_sorter)
        {
            // Calculate the theoretical product masses and store them in
            // product_masses_buf, which is aliased under the more informative
            // name theoretical_product_masses for the code below.
            TotalProducts = Peptide.CalculateProductMasses(PRODUCT_TYPES[Spectrum.FragmentationMethod],
                                                           ref product_masses_buf, fast_q_sorter);
            double[] theoretical_product_masses = product_masses_buf;

            // speed optimizations
            int num_theoretical_products = TotalProducts;
            double[] experimental_masses = Spectrum.Masses;
            double[] experimental_intensities = Spectrum.Intensities;
            int num_experimental_peaks = experimental_masses.Length;
            double product_mass_tolerance_value = productMassTolerance.Value;
            MassToleranceUnits product_mass_tolerance_units = productMassTolerance.Units;

            MatchingProducts = 0;
            int t = 0;
            int e = 0;
            while(t < num_theoretical_products && e < num_experimental_peaks)
            {
                double mass_difference = experimental_masses[e] - theoretical_product_masses[t];
                if(product_mass_tolerance_units == MassToleranceUnits.ppm)
                {
                    mass_difference = mass_difference / theoretical_product_masses[t] * 1e6;
                }
                if(Math.Abs(mass_difference) <= product_mass_tolerance_value)
                {
                    MatchingProducts++;
                    t++;
                }
                else if(mass_difference < 0)
                {
                    e++;
                }
                else if(mass_difference > 0)
                {
                    t++;
                }
            }
            MatchingProductsFraction = (double)MatchingProducts / TotalProducts;

            MatchingIntensity = 0.0;
            int e2 = 0;
            int t2 = 0;
            while(e2 < num_experimental_peaks && t2 < num_theoretical_products)
            {
                double mass_difference = experimental_masses[e2] - theoretical_product_masses[t2];
                if(product_mass_tolerance_units == MassToleranceUnits.ppm)
                {
                    mass_difference = mass_difference / theoretical_product_masses[t2] * 1e6;
                }
                if(Math.Abs(mass_difference) <= product_mass_tolerance_value)
                {
                    MatchingIntensity += experimental_intensities[e2];
                    e2++;
                }
                else if(mass_difference < 0)
                {
                    e2++;
                }
                else if(mass_difference > 0)
                {
                    t2++;
                }
            }
            MatchingIntensityFraction = MatchingIntensity / Spectrum.TotalIntensity;

            MorpheusScore = MatchingProducts + MatchingIntensityFraction;
        }
        // This Init method needs to be called before this object can be used.
        // For more info, see how we use these objects in DatabaseSearcher.
        //
        // We copy the peptide parameter deeply (because these sometimes come
        // from reusable buffers) but not the spectrum parameter (because these
        // are not reused).
        //
        // The array product_masses_buf is used for temporary internal storage
        // and may be resized. It needs to be local to the current thread; no
        // locking is performed. Its contents are not of interest to the
        // caller.
        //
        // The fast_q_sorter object also need to be local to the current
        // thread, as its internal state will be modified.
        public void Init(TandemMassSpectrum spectrum, Peptide peptide, MassTolerance productMassTolerance,
            ref double[] product_masses_buf, FastQSorter fast_q_sorter)
        {
            Spectrum = spectrum;
            if(Peptide == null)
                Peptide = new Peptide();
            Peptide.CopyFrom(peptide);

            PrecursorMassErrorDa = spectrum.PrecursorMass - (precursorMassType == MassType.Average ? peptide.AverageMass : peptide.MonoisotopicMass);
            PrecursorMassErrorPpm = PrecursorMassErrorDa / (precursorMassType == MassType.Average ? peptide.AverageMass : peptide.MonoisotopicMass) * 1e6;

            ScoreMatch(productMassTolerance, ref product_masses_buf, fast_q_sorter);
        }