예제 #1
0
        protected virtual void GetRawData(out List <double> vectMZs, out List <double> vectIntensities, int scan,
                                          double min_mz, double max_mz, bool centroid)
        {
            if (max_mz <= min_mz)
            {
                throw new Exception("max_mz should be greater than min_mz");
            }

            vectMZs         = new List <double>();
            vectIntensities = new List <double>();
            List <double> allMZs;
            List <double> allIntensities;

            GetRawData(out allMZs, out allIntensities, scan, centroid);
            var numPts = allMZs.Count;

            if (numPts <= 1)
            {
                Console.Error.WriteLine(scan);
                throw new Exception("mz_vector empty in GetRawData in RawData.cpp");
            }
            var startIndex = PeakIndex.GetNearestBinary(allMZs, min_mz, 0, numPts - 1);
            var stopIndex  = PeakIndex.GetNearestBinary(allMZs, max_mz, 0, numPts - 1);

            if ((stopIndex - startIndex) <= 1) //nothing in this m/z range
            {
                return;
            }

            vectMZs.AddRange(allMZs.GetRange(startIndex, stopIndex - startIndex));
            vectIntensities.AddRange(allIntensities.GetRange(startIndex, stopIndex - startIndex));
        }
        /// <summary>
        ///     Gets the charge state (determined by AutoCorrelation algorithm) for a peak in some data.
        /// </summary>
        /// <param name="peak">is the peak whose charge we want to detect.</param>
        /// <param name="peakData">is the PeakData object containing raw data, peaks, etc which are used in the process.</param>
        /// <param name="debug"></param>
        /// <returns>Returns the charge of the feature.</returns>
        public static int GetChargeState(ThrashV1Peak peak, PeakData peakData, bool debug)
        {
            var minus      = 0.1;
            var plus       = 1.1; // right direction to look
            var startIndex = PeakIndex.GetNearest(peakData.MzList, peak.Mz - peak.FWHM - minus, peak.DataIndex);
            var stopIndex  = PeakIndex.GetNearest(peakData.MzList, peak.Mz + peak.FWHM + plus, peak.DataIndex);
            var numPts     = stopIndex - startIndex;
            var numL       = numPts;

            if (numPts < 5)
            {
                return(-1);
            }

            if (numPts < 256)
            {
                numL = 10 * numPts;
            }

            // TODO: PattersonChargeStateCalculator does a lot of funny stuff around here.
            // variable to help us perform spline interpolation.
            // count is stopIndex - startIndex + 1 because we need to include the values at stopIndex as well
            // NOTE: This output is different from what the DeconEngineV2 code outputs; there are notes in that code
            //    wondering if there was a bug in the previous implementation imported from VB, of starting at startIndex + 1.
            //    That code performed interpolation on the range from startIndex + 1 to stopIndex, inclusive, and minMz set to PeakData.MzList[startIndex + 1].
            //    This code can produce output that more closely matches the DeconEngineV2 output by using
            //    "startIndex, stopIndex - startIndex + 2" as the parameters to "GetRange()", and setting minMz to PeakData.MzList[startIndex + 1].
            //    Since using startIndex and stopIndex directly produces output that mostly differs on fit score by a small amount,
            //    we are changing this code to use them.
            var interpolator = CubicSpline.InterpolateNaturalSorted(
                peakData.MzList.GetRange(startIndex, stopIndex - startIndex + 1).ToArray(),
                peakData.IntensityList.GetRange(startIndex, stopIndex - startIndex + 1).ToArray());

            var minMz = peakData.MzList[startIndex];
            var maxMz = peakData.MzList[stopIndex];

            // List to store the interpolated intensities of the region on which we performed the cubic spline interpolation.
            var iv = new List <double>(numL);

            for (var i = 0; i < numL; i++)
            {
                var xVal = minMz + (maxMz - minMz) * i / numL;
                var fVal = interpolator.Interpolate(xVal);
                iv.Add(fVal);
            }

            if (debug)
            {
                Console.Error.WriteLine("mz,intensity");
                for (var i = 0; i < numL; i++)
                {
                    var xVal = minMz + (maxMz - minMz) * i / numL;
                    Console.Error.WriteLine(xVal + "," + iv[i]);
                }
            }

            // List to store the auto correlation values at the points in the region.
            var autoCorrelationScores = ACss(iv.ToArray());

            if (debug)
            {
                Console.Error.WriteLine("AutoCorrelation values");
                for (var i = 0; i < autoCorrelationScores.Count; i++)
                {
                    var score = autoCorrelationScores[i];
                    Console.Error.WriteLine((maxMz - minMz) * i / numL + "," + score);
                }
            }

            var minN = 0;

            while (minN < numL - 1 && autoCorrelationScores[minN] > autoCorrelationScores[minN + 1])
            {
                minN++;
            }
            var success = HighestChargeStatePeak(minMz, maxMz, minN, autoCorrelationScores, MaxCharge, out var bestAcScore, out _);

            if (!success)
            {
                return(-1); // Didn't find anything
            }
            // List to temporarily store charge list. These charges are calculated at peak values of auto correlation.
            // Now go back through the CS peaks and make a list of all CS that are at least 10% of the highest
            var charges = GenerateChargeStates(minMz, maxMz, minN, autoCorrelationScores, MaxCharge, bestAcScore);

            // Get the final CS value to be returned
            var returnChargeStateVal = -1;
            // TODO: PattersonChargeStateCalculator really doesn't match the following code.
            var fwhm = peak.FWHM; // Store a copy of the FWHM to avoid modifying the actual value

            if (fwhm > 0.1)
            {
                fwhm = 0.1;
            }

            for (var i = 0; i < charges.Count; i++)
            {
                // no point retesting previous charge.
                var tempChargeState = charges[i];
                var skip            = false;
                for (var j = 0; j < i; j++)
                {
                    if (charges[j] == tempChargeState)
                    {
                        skip = true;
                        break;
                    }
                }
                if (skip)
                {
                    continue;
                }
                if (tempChargeState > 0)
                {
                    var peakA = peak.Mz + 1.0 / tempChargeState;
                    var found = peakData.GetPeakFromAllOriginalIntensity(peakA - fwhm, peakA + fwhm, out var isoPeak);
                    if (found)
                    {
                        returnChargeStateVal = tempChargeState;
                        if (isoPeak.Mz * tempChargeState < 3000)
                        {
                            break;
                        }
                        // if the mass is greater than 3000, lets make sure that multiple isotopes exist.
                        peakA = peak.Mz - 1.03 / tempChargeState;
                        found = peakData.GetPeakFromAllOriginalIntensity(peakA - fwhm, peakA + fwhm, out isoPeak);
                        if (found)
                        {
                            return(tempChargeState);
                        }
                    }
                    else
                    {
                        peakA = peak.Mz - 1.0 / tempChargeState;
                        found = peakData.GetPeakFromAllOriginalIntensity(peakA - fwhm, peakA + fwhm, out isoPeak);
                        if (found && isoPeak.Mz * tempChargeState < 3000)
                        {
                            return(tempChargeState);
                        }
                    }
                }
            }
            return(returnChargeStateVal);
        }
        public bool FindPeak(double minMz, double maxMz, out double mzValue, out double intensity, bool debug)
        {
            if (!_lastValueWasCached)
            {
                var found = IsotopeDistribution.FindPeak(minMz, maxMz, out mzValue, out intensity);
                return(found);
            }

            mzValue   = 0;
            intensity = 0;
            var numPts = TheoreticalDistMzs.Count;

            var index = PeakIndex.GetNearestBinary(TheoreticalDistMzs, minMz, 0, numPts - 1);

            if (index >= numPts)
            {
                return(false);
            }

            if (TheoreticalDistMzs[index] > minMz)
            {
                while (index > 0 && TheoreticalDistMzs[index] > minMz)
                {
                    index--;
                }
            }
            else
            {
                while (index < numPts && TheoreticalDistMzs[index] < minMz)
                {
                    index++;
                }
                index--;
            }

            //find index of peak with maximum intensity
            var maxIndex = -1;

            for (; index < numPts; index++)
            {
                var mz = TheoreticalDistMzs[index];
                if (mz > maxMz)
                {
                    break;
                }
                if (mz > minMz)
                {
                    if (TheoreticalDistIntensities[index] > intensity)
                    {
                        maxIndex  = index;
                        intensity = TheoreticalDistIntensities[index];
                    }
                }
            }
            if (maxIndex == -1)
            {
                return(false);
            }

            var x2 = TheoreticalDistMzs[maxIndex];
            var x1 = x2 - 1.0 / IsotopeDistribution.PointsPerAmu;
            var x3 = x2 + 1.0 / IsotopeDistribution.PointsPerAmu;

            if (maxIndex > 0 && maxIndex < numPts - 1)
            {
                var y1 = TheoreticalDistIntensities[maxIndex - 1];
                var y2 = TheoreticalDistIntensities[maxIndex];
                var y3 = TheoreticalDistIntensities[maxIndex + 1];

                // if the points are cached, these could be single sticks with surrounding
                // points below background. To avoid that case, lets just check
                // and see if the differences in the theoretical mz values is as
                // expected or not.
                if (TheoreticalDistMzs[maxIndex - 1] > x2 - 2.0 / IsotopeDistribution.PointsPerAmu &&
                    TheoreticalDistMzs[maxIndex + 1] < x2 + 2.0 / IsotopeDistribution.PointsPerAmu)
                {
                    var d = (y2 - y1) * (x3 - x2); //[gord] slope?  what is this?...  Denominator... see below
                    d = d - (y3 - y2) * (x2 - x1); //

                    if (d.Equals(0))
                    {
                        mzValue = x2;
                    }
                    else
                    {
                        mzValue = (x1 + x2 - (y2 - y1) * (x3 - x2) * (x1 - x3) / d) / 2.0;
                    }
                    //[gord] what's this doing?? Looks like a mid-point calculation
                }
                else
                {
                    mzValue   = x2;
                    intensity = TheoreticalDistIntensities[maxIndex];
                }
                return(true);
            }

            mzValue   = x2;
            intensity = TheoreticalDistIntensities[maxIndex];
            return(true);
        }
        /// <summary>
        ///     gets the intensity for a given mz.
        /// </summary>
        /// <remarks>
        ///     We look for the intensity at a given m/z value in the raw data List mzs
        ///     (the intensities are stored in the corresponding raw data intensity List intensities).
        ///     If the value does not exist, we interpolate the intensities of points before and after this m/z value.
        /// </remarks>
        /// <param name="mz">the m/z value for which we want to find the intensity.</param>
        /// <param name="mzs">pointer to List with observed m/z values.</param>
        /// <param name="intensities">pointer to List with observed intensity values.</param>
        /// <returns>
        ///     returns the intensity of the peak which has the given m/z. If the exact peak is not present,
        ///     then we interpolate the intensity. If the m/z value is greater than the maximum mz or less,
        ///     then the minimum m/z, 0 is returned.
        /// </returns>
        public double GetPointIntensity(double mz, List <double> mzs, List <double> intensities)
        {
            if ((Mz1 < mz && Mz2 < mz) || (Mz1 > mz && Mz2 > mz))
            {
                var numpts = mzs.Count;
                if (LastPointIndex >= numpts)
                {
                    LastPointIndex = -1;
                }

                //since points are more likely to be searched in order.
                if (LastPointIndex != -1 && Mz2 < mz)
                {
                    if (LastPointIndex < numpts - 1 && mzs[LastPointIndex + 1] > mz)
                    {
                        LastPointIndex++;
                    }
                    else
                    {
                        LastPointIndex = PeakIndex.GetNearestBinary(mzs, mz, LastPointIndex,
                                                                    numpts - 1);
                    }
                }
                else
                {
                    LastPointIndex = PeakIndex.GetNearestBinary(mzs, mz, 0, numpts - 1);
                }
                if (LastPointIndex >= numpts)
                {
                    return(0);
                }

                if (LastPointIndex < 0)
                {
                    LastPointIndex = 0;
                }

                if (mzs[LastPointIndex] > mz)
                {
                    while (LastPointIndex > 0 && mzs[LastPointIndex] > mz)
                    {
                        LastPointIndex--;
                    }
                }
                else
                {
                    while (LastPointIndex < numpts && mzs[LastPointIndex] < mz)
                    {
                        LastPointIndex++;
                    }
                    LastPointIndex--;
                }

                if (LastPointIndex == numpts - 1)
                {
                    LastPointIndex = numpts - 2;
                }

                Mz1 = mzs[LastPointIndex];
                Mz2 = mzs[LastPointIndex + 1];

                Intensity1 = intensities[LastPointIndex];
                Intensity2 = intensities[LastPointIndex + 1];
            }
            if (Mz1.Equals(Mz2))
            {
                return(Intensity1);
            }

            return((mz - Mz1) / (Mz2 - Mz1) * (Intensity2 - Intensity1) + Intensity1);
        }