Exemple #1
0
        private void SetIsotopeDistributionToZero(PeakData peakData, ThrashV1Peak peak, double zeroingStartMz,
                                                  double zeroingStopMz, double monoMw, int chargeState, bool clearSpectrum, HornTransformResults record,
                                                  bool debug = false)
        {
            var peakIndices = new List <int>();

            peakIndices.Add(peak.PeakIndex);
            var mzDelta = record.DeltaMz;

            if (debug)
            {
                Console.Error.WriteLine("Clearing peak data for " + peak.Mz + " Delta = " + mzDelta);
                Console.Error.WriteLine("Zeroing range = " + zeroingStartMz + " to " + zeroingStopMz);
            }

            double maxMz = 0;

            if (IsO16O18Data)
            {
                maxMz = (monoMw + 3.5) / chargeState + ChargeCarrierMass;
            }

            var numUnprocessedPeaks = peakData.GetNumUnprocessedPeaks();

            if (numUnprocessedPeaks == 0)
            {
                record.IsotopePeakIndices.Add(peak.PeakIndex);
                return;
            }

            if (clearSpectrum)
            {
                if (debug)
                {
                    Console.Error.WriteLine("Deleting main peak :" + peak.Mz);
                }
                SetPeakToZero(peak.DataIndex, ref peakData.IntensityList, ref peakData.MzList, debug);
            }

            peakData.RemovePeaks(peak.Mz - peak.FWHM, peak.Mz + peak.FWHM, debug);

            if (1 / (peak.FWHM * chargeState) < 3) // gord:  ??
            {
                record.IsotopePeakIndices.Add(peak.PeakIndex);
                peakData.RemovePeaks(zeroingStartMz, zeroingStopMz, debug);
                return;
            }

            // Delete isotopes of mzs higher than mz of starting isotope
            for (var peakMz = peak.Mz + 1.003 / chargeState;
                 (!IsO16O18Data || peakMz <= maxMz) && peakMz <= zeroingStopMz + 2 * peak.FWHM;
                 peakMz += 1.003 / chargeState)
            {
                if (debug)
                {
                    Console.Error.WriteLine("\tFinding next peak top from " + (peakMz - 2 * peak.FWHM) + " to " +
                                            (peakMz + 2 * peak.FWHM) + " pk = " + peakMz + " FWHM = " + peak.FWHM);
                }
                ThrashV1Peak nextPeak;
                peakData.GetPeakFromAll(peakMz - 2 * peak.FWHM, peakMz + 2 * peak.FWHM, out nextPeak);

                if (nextPeak.Mz.Equals(0))
                {
                    if (debug)
                    {
                        Console.Error.WriteLine("\t\tNo peak found.");
                    }
                    break;
                }
                if (debug)
                {
                    Console.Error.WriteLine("\t\tFound peak to delete =" + nextPeak.Mz);
                }

                // Before assuming that the next peak is indeed an isotope, we must check for the height of this
                // isotope. If the height is greater than expected by a factor of 3, lets not delete it.
                peakIndices.Add(nextPeak.PeakIndex);
                SetPeakToZero(nextPeak.DataIndex, ref peakData.IntensityList, ref peakData.MzList, debug);

                peakData.RemovePeaks(nextPeak.Mz - peak.FWHM, nextPeak.Mz + peak.FWHM, debug);
                peakMz = nextPeak.Mz;
            }

            // Delete isotopes of mzs lower than mz of starting isotope
            // TODO: Use the delta m/z to make sure to remove 1- peaks from the unprocessed list, but not from the list of peaks?
            for (var peakMz = peak.Mz - 1.003 / chargeState;
                 peakMz > zeroingStartMz - 2 * peak.FWHM;
                 peakMz -= 1.003 / chargeState)
            {
                if (debug)
                {
                    Console.Error.WriteLine("\tFinding previous peak top from " + (peakMz - 2 * peak.FWHM) + " to " +
                                            (peakMz + 2 * peak.FWHM) + " pk = " + peakMz + " FWHM = " + peak.FWHM);
                }
                ThrashV1Peak nextPeak;
                peakData.GetPeakFromAll(peakMz - 2 * peak.FWHM, peakMz + 2 * peak.FWHM, out nextPeak);
                if (nextPeak.Mz.Equals(0))
                {
                    if (debug)
                    {
                        Console.Error.WriteLine("\t\tNo peak found.");
                    }
                    break;
                }
                if (debug)
                {
                    Console.Error.WriteLine("\t\tFound peak to delete =" + nextPeak.Mz);
                }
                peakIndices.Add(nextPeak.PeakIndex);
                SetPeakToZero(nextPeak.DataIndex, ref peakData.IntensityList, ref peakData.MzList, debug);
                peakData.RemovePeaks(nextPeak.Mz - peak.FWHM, nextPeak.Mz + peak.FWHM, debug);
                peakMz = nextPeak.Mz;
            }

            if (debug)
            {
                Console.Error.WriteLine("Done Clearing peak data for " + peak.Mz);
            }

            peakIndices.Sort();
            // now insert into array.
            var numPeaksObserved       = peakIndices.Count;
            var numIsotopesObserved    = 0;
            var lastIsotopeNumObserved = int.MinValue;

            for (var i = 0; i < numPeaksObserved; i++)
            {
                var currentIndex = peakIndices[i];
                var currentPeak  = new ThrashV1Peak(peakData.PeakTops[currentIndex]);
                var isotopeNum   = (int)(Math.Abs((currentPeak.Mz - peak.Mz) * chargeState / 1.003) + 0.5);
                if (currentPeak.Mz < peak.Mz)
                {
                    isotopeNum = -1 * isotopeNum;
                }
                if (isotopeNum > lastIsotopeNumObserved)
                {
                    lastIsotopeNumObserved = isotopeNum;
                    numIsotopesObserved++;
                    if (numIsotopesObserved > MaxIsotopes)
                    {
                        break;
                    }
                    record.IsotopePeakIndices.Add(peakIndices[i]);
                }
                else
                {
                    record.IsotopePeakIndices[numIsotopesObserved - 1] = peakIndices[i];
                }
            }
            if (debug)
            {
                Console.Error.WriteLine("Copied " + record.NumIsotopesObserved + " isotope peak indices into record ");
            }
        }
        /// <summary>
        ///     calculates the fit score for a peak.
        /// </summary>
        /// <param name="peakData"> variable which stores the data itself</param>
        /// <param name="chargeState"> charge state at which we want to compute the peak.</param>
        /// <param name="peak"> peak for which we want to compute the fit function.</param>
        /// <param name="isoRecord">stores the result of the fit.</param>
        /// <param name="deleteIntensityThreshold">intensity of least isotope to delete.</param>
        /// <param name="minTheoreticalIntensityForScore">minimum intensity of point to consider for scoring purposes.</param>
        /// <param name="leftFitStringencyFactor"></param>
        /// <param name="rightFitStringencyFactor"></param>
        /// <param name="pointsUsed">Number of points used</param>
        /// <param name="debug">enable debugging output</param>
        /// <remarks>
        ///     This fitter is used by MassTransform.cpp.   It does more than just get a fit score. It first
        ///     gets a fit score and then slides to the left until the fit score does not improve and then resets
        ///     to the center point and then slides to the right until the fit score does not improve. Returns the
        ///     best fit score and fills the isotopic profile (isotopeFitRecord)
        /// </remarks>
        public double GetFitScore(PeakData peakData, int chargeState, ref ThrashV1Peak peak,
                                  out HornTransformResults isoRecord, double deleteIntensityThreshold, double minTheoreticalIntensityForScore,
                                  double leftFitStringencyFactor, double rightFitStringencyFactor, out int pointsUsed, bool debug = false)
        {
            isoRecord = new HornTransformResults();
            if (chargeState <= 0)
            {
                Console.WriteLine("Negative value for charge state. " + chargeState);
                Environment.Exit(1);
            }
            //initialize
            var peakMass = (peak.Mz - ChargeCarrierMass) * chargeState;

            // by now the cc_mass, tag formula and media options in Mercury(Isotope generation)
            // should be set.
            if (debug)
            {
                Console.WriteLine("\n\n-------------------- BEGIN TRANSFORM ---------------------------" + chargeState);
                Console.WriteLine("Getting isotope distribution for mass = " + peakMass + " mz = " + peak.Mz +
                                  " charge = " + chargeState);
            }
            var resolution = peak.Mz / peak.FWHM;

            // DJ Jan 07 2007: Need to get all peaks down to delete interval so that range of deletion is correct.
            //GetIsotopeDistribution(peakMass, chargeState, resolution, TheoreticalDistMzs, TheoreticalDistIntensities,
            //  deleteIntensityThreshold, debug);
            GetIsotopeDistribution(peakMass, chargeState, resolution, out TheoreticalDistMzs,
                                   out TheoreticalDistIntensities, deleteIntensityThreshold, debug);
            var theorPeakData = GetTheoreticalIsotopicDistributionPeakList(TheoreticalDistMzs,
                                                                           TheoreticalDistIntensities);
            var numpeaks = theorPeakData.GetNumPeaks();

            if (debug)
            {
                Console.WriteLine("---------------------------------------- THEORETICAL PEAKS ------------------");
                Console.WriteLine("Theoretical peak\t" + "Index\t" + "MZ\t" + "Intensity\t" + "FWHM\t" + "SigNoise");
                for (var i = 0; i < numpeaks; i++)
                {
                    ThrashV1Peak theorpeak;
                    theorPeakData.GetPeak(i, out theorpeak);
                    Console.WriteLine("Theoretical peak\t" + i + "\t" + theorpeak.Mz + "\t" +
                                      theorpeak.Intensity + "\t" + theorpeak.FWHM + "\t" + theorpeak.SignalToNoiseDbl);
                }
                Console.WriteLine("----------------------------------- END THEORETICAL PEAKS ------------------");
            }

            // Anoop April 9 2007: For checking if the distribution does not overlap/link with any other distribution
            // Beginnings of deisotoping correction
            //bool is_linked = false;
            //is_linked =  IsIsotopeLinkedDistribution(deleteIntensityThreshold);
            var delta = peak.Mz - IsotopeDistribution.MaxPeakMz;

            //if(debug)
            //  System.Console.WriteLine("Going for first fit");
            var fit = FitScore(peakData, chargeState, peak, delta, minTheoreticalIntensityForScore, out pointsUsed,
                               debug);

            if (debug)
            {
                Console.WriteLine("Peak\tPeakIdx\tmz\tintens\tSN\tFWHM\tfit\tdelta");
                Console.WriteLine("CENTER\t" + peak.PeakIndex + "\t" + peak.Mz + "\t" + peak.Intensity +
                                  "\t" + peak.SignalToNoiseDbl + "\t" + peak.FWHM + "\t" + fit + "\t" + delta + "\t");
            }

            if (!UseThrash)
            {
                isoRecord.Fit           = fit;
                isoRecord.FitCountBasis = pointsUsed;
                isoRecord.Mz            = peak.Mz;
                isoRecord.AverageMw     = IsotopeDistribution.AverageMw + delta * chargeState;
                isoRecord.MonoMw        = IsotopeDistribution.MonoMw + delta * chargeState;
                isoRecord.MostIntenseMw = IsotopeDistribution.MostIntenseMw + delta * chargeState;
                isoRecord.DeltaMz       = delta;
                return(fit);
            }

            double p1Fit = -1, m1Fit = -1; // [gord]: this seems unused
            var    mPeak    = IsotopeDistribution.MaxPeakMz;
            var    nextPeak = new ThrashV1Peak();

            var bestFit           = fit;
            var bestFitCountBasis = pointsUsed;
            var bestDelta         = delta;
            //double maxY = peak.mdbl_intensity;

            var fitCountBasis = 0;

            //------------- Slide to the LEFT --------------------------------------------------
            for (var dd = 1.003 / chargeState; dd <= 10.03 / chargeState; dd += 1.003 / chargeState)
            {
                double mzLeft;
                double intensityLeft;

                //check for theoretical peak to the right of TheoreticalMaxPeak; store mz and intensity
                var foundPeak = FindPeak(mPeak + dd - 0.2 / chargeState, mPeak + dd + 0.2 / chargeState, out mzLeft,
                                         out intensityLeft,
                                         debug);

                // if the above theoretical peak was found,  look one peak to the LEFT in the Experimental peaklist
                if (foundPeak)
                {
                    peakData.FindPeak(peak.Mz - dd - peak.FWHM, peak.Mz - dd + peak.FWHM,
                                      out nextPeak);
                }

                if (mzLeft > 0 && nextPeak.Mz > 0)
                //if there is a theoreticalPeak to the RIGHT of theoreticalMaxPeak AND there is an experimentalPeak to the LEFT of experimentalMaxPeak...
                {
                    delta = peak.Mz - mzLeft;
                    // essentially, this shifts the theoretical over to the left and gets the delta; then check the fit
                    var currentPeakCopy = new ThrashV1Peak(peak); // in c++ this copy is created by value;
                    currentPeakCopy.Intensity = nextPeak.Intensity;
                    fit = FitScore(peakData, chargeState, currentPeakCopy, delta, minTheoreticalIntensityForScore,
                                   out fitCountBasis, debug);
                    if (debug)
                    {
                        //System.Console.WriteLine(" isotopes. Fit =" + fit + " Charge = " + cs + " Intensity = " + nxt_peak.mdbl_intensity + " delta = " + delta);
                        Console.WriteLine("LEFT\t" + nextPeak.PeakIndex + "\t" + nextPeak.Mz + "\t" +
                                          nextPeak.Intensity + "\t" + nextPeak.SignalToNoiseDbl + "\t" + nextPeak.FWHM +
                                          "\t" + fit + "\t" + delta);
                    }
                }
                else
                {
                    if (debug)
                    {
                        Console.WriteLine("LEFT\t" + -1 + "\t" + -1 + "\t" + -1 + "\t" + -1 + "\t" + -1 + "\t" + -1 +
                                          "\t" + -1);
                    }
                    fit = bestFit + 1000; // make the fit terrible
                }
                // TODO: Currently, if fit score is less than best_fit, iteration stops.  Future versions should continue attempted fitting if fit was within a specified range of the best fit
                // 26th February 2007 Deep Jaitly

                /*if (fit <= bestFit)
                 * {
                 *  if (nextPeak.mdbl_intensity > peak.mdbl_intensity)
                 *      peak.mdbl_intensity = nextPeak.mdbl_intensity;
                 *  maxY = peak.mdbl_intensity;
                 *  bestFit = fit;
                 *  bestDelta = delta;
                 * }*/
                var leftFitFactor = fit / bestFit;
                if (leftFitFactor <= leftFitStringencyFactor)
                {
                    if (nextPeak.Intensity > peak.Intensity)
                    {
                        peak.Intensity = nextPeak.Intensity;
                    }
                    //maxY = peak.mdbl_intensity;
                    bestFit           = fit;
                    bestFitCountBasis = fitCountBasis;
                    bestDelta         = delta;
                }
                else
                {
                    if (p1Fit.Equals(-1)) //[gord]   what is this doing?  Peak1 fit??
                    {
                        p1Fit = fit;
                    }
                    if (!CompleteFitThrash)
                    {
                        break;
                    }
                }
            }

            //if (debug)
            //      System.Console.WriteLine("\n---------------- Sliding to the RIGHT -------------------------";
            for (var dd = 1.003 / chargeState; dd <= 10.03 / chargeState; dd += 1.003 / chargeState)
            {
                double mzRight;
                double intensityRight;
                ////check for theoretical peak to the LEFT of TheoreticalMaxPeak; store mz and intensity
                var foundPeak = FindPeak(mPeak - dd - 0.2 / chargeState, mPeak - dd + 0.2 / chargeState, out mzRight,
                                         out intensityRight,
                                         debug);

                // if the above theoretical peak was found,  look one peak to the RIGHT in the Experimental peaklist
                if (foundPeak)
                {
                    peakData.FindPeak(peak.Mz + dd - peak.FWHM, peak.Mz + dd + peak.FWHM,
                                      out nextPeak);
                }

                if (mzRight > 0 && nextPeak.Mz > 0)
                {
                    delta = peak.Mz - mzRight;
                    var currentPeakCopy = new ThrashV1Peak(peak);
                    currentPeakCopy.Intensity = nextPeak.Intensity;
                    fit = FitScore(peakData, chargeState, currentPeakCopy, delta, minTheoreticalIntensityForScore,
                                   out fitCountBasis, debug);
                    //fit = FitScore(pk_data, cs, nxt_peak.mdbl_intensity, delta);
                    if (debug)
                    {
                        //System.Console.WriteLine(" isotopes. Fit =" + fit + " Charge = " + chargeState + " Intensity = " + nextPeak.mdbl_intensity + " delta = " + delta);
                        Console.WriteLine("RIGHT\t" + nextPeak.PeakIndex + "\t" + nextPeak.Mz + "\t" +
                                          nextPeak.Intensity + "\t" + nextPeak.SignalToNoiseDbl + "\t" + nextPeak.FWHM +
                                          "\t" + fit + "\t" + delta);
                    }
                }
                else
                {
                    fit = bestFit + 1000; //force it to be a bad fit
                    if (debug)
                    {
                        //  System.Console.WriteLine("No peak found");
                        Console.WriteLine("RIGHT\t" + -1 + "\t" + -1 + "\t" + -1 + "\t" + -1 + "\t" + -1 + "\t" + -1 +
                                          "\t" + -1);
                    }
                }

                /*if (fit <= bestFit)
                 * {
                 * if (nextPeak.mdbl_intensity > peak.mdbl_intensity)
                 * peak.mdbl_intensity = nextPeak.mdbl_intensity;
                 * MaxY = peak.mdbl_intensity;
                 * bestFit = fit;
                 * bestDelta = delta;
                 * }*/
                var rightFitFactor = fit / bestFit;
                if (rightFitFactor <= rightFitStringencyFactor)
                {
                    if (nextPeak.Intensity > peak.Intensity)
                    {
                        peak.Intensity = nextPeak.Intensity;
                    }
                    //maxY = peak.mdbl_intensity;
                    bestFit           = fit;
                    bestFitCountBasis = fitCountBasis;
                    bestDelta         = delta;
                }
                else
                {
                    if (m1Fit.Equals(-1))
                    {
                        m1Fit = fit;
                    }
                    if (!CompleteFitThrash)
                    {
                        break;
                    }
                }
            }

            //double theorIntensityCutoff = 30; //
            //double peakWidth = peak.mdbl_FWHM;
            if (debug)
            {
                Console.WriteLine("Std delta = \t" + bestDelta);
            }
            //best_delta = CalculateDeltaFromSeveralObservedPeaks(best_delta, peakWidth, pk_data, theorPeakData, theorIntensityCutoff);
            if (debug)
            {
                Console.WriteLine("Weighted delta = \t" + bestDelta);
            }

            isoRecord.Fit           = bestFit;
            isoRecord.FitCountBasis = bestFitCountBasis;
            isoRecord.ChargeState   = chargeState;
            isoRecord.Mz            = peak.Mz;
            isoRecord.DeltaMz       = bestDelta;
            isoRecord.AverageMw     = IsotopeDistribution.AverageMw + bestDelta * chargeState;
            isoRecord.MonoMw        = IsotopeDistribution.MonoMw + bestDelta * chargeState;
            isoRecord.MostIntenseMw = IsotopeDistribution.MostIntenseMw + bestDelta * chargeState;

            //iso_record.mbln_flag_isotope_link = is_linked;
            pointsUsed = bestFitCountBasis;
            return(bestFit);
        }
Exemple #3
0
        protected virtual bool FindTransform(PeakData peakData, ref ThrashV1Peak peak, out HornTransformResults record,
                                             double backgroundIntensity = 0)
        {
            SetIsotopeFitScorerOptions();
            record = new HornTransformResults();
            if (peak.SignalToNoiseDbl < MinSignalToNoise || peak.FWHM.Equals(0))
            {
                return(false);
            }

            //var resolution = peak.Mz / peak.FWHM;
            /**/
            var chargeState = AutoCorrelationChargeDetermination.GetChargeState(peak, peakData, ShowTraceMessages);

            /*/
             * // This chunk of code tries to use the DeconTools Patterson Algorithm Charge State Calculator, but it gets vastly different results.
             * var xyData = new XYData();
             * var mzArray = peakData.MzList.ToArray();
             * var intensityArray = peakData.IntensityList.ToArray();
             * xyData.SetXYValues(ref mzArray, ref intensityArray);
             * var peakList = new List<Peak>();
             * for (int i = 0; i < peakData.MzList.Count; i++)
             * {
             *  peakList.Add(new Peak(peakData.MzList[i], (float)peakData.IntensityList[i], 1));
             * }
             * var chargeState = DeconTools.Backend.Algorithms.ChargeStateDetermination.PattersonAlgorithm.PattersonChargeStateCalculator.GetChargeState(xyData, peakList, convertDeconPeakToMSPeak(peak));
             * /**/

            if (chargeState == -1 && CheckPatternsAgainstChargeOne)
            {
                chargeState = 1;
            }

            if (ShowTraceMessages)
            {
                Console.Error.WriteLine("Deisotoping :" + peak.Mz);
                Console.Error.WriteLine("Charge = " + chargeState);
            }

            if (chargeState == -1)
            {
                return(false);
            }

            if ((peak.Mz + ChargeCarrierMass) * chargeState > MaxMWAllowed)
            {
                return(false);
            }

            if (IsO16O18Data)
            {
                if (peak.FWHM < 1.0 / chargeState)
                {
                    // move back by 4 Da and see if there is a peak.
                    var          minMz = peak.Mz - 4.0 / chargeState - peak.FWHM;
                    var          maxMz = peak.Mz - 4.0 / chargeState + peak.FWHM;
                    ThrashV1Peak o16Peak;
                    var          found = peakData.GetPeak(minMz, maxMz, out o16Peak);
                    if (found && !o16Peak.Mz.Equals(peak.Mz))
                    {
                        // put back the current into the to be processed list of peaks.
                        peakData.AddPeakToProcessingList(peak);
                        // reset peak to the right peak so that the calling function may
                        // know that the peak might have changed in the O16/O18 business
                        peak = o16Peak;
                        peakData.RemovePeak(peak);
                        return(FindTransform(peakData, ref peak, out record, backgroundIntensity));
                    }
                }
            }

            var peakCharge1 = new ThrashV1Peak(peak);

            // Until now, we have been using constant theoretical delete intensity threshold..
            // instead, from now, we should use one that is proportional to intensity, for more intense peaks.
            // However this will not solve all problems. If thrashing occurs, then the peak intensity will
            // change when the function returns and we may not delete far enough.
            //double deleteThreshold = backgroundIntensity / peak.Intensity * 100;
            //if (backgroundIntensity ==0 || deleteThreshold > _deleteIntensityThreshold)
            //  deleteThreshold = _deleteIntensityThreshold;
            var deleteThreshold = DeleteIntensityThreshold;
            int fitCountBasis;
            var bestFit = _isotopeFitScorer.GetFitScore(peakData, chargeState, ref peak, out record, deleteThreshold,
                                                        MinIntensityForScore, LeftFitStringencyFactor, RightFitStringencyFactor, out fitCountBasis,
                                                        ShowTraceMessages);

            // When deleting an isotopic profile, this value is set to the first m/z to perform deletion at.
            double zeroingStartMz;
            // When deleting an isotopic profile, this value is set to the last m/z to perform deletion at.
            double zeroingStopMz;

            _isotopeFitScorer.GetZeroingMassRange(out zeroingStartMz, out zeroingStopMz, record.DeltaMz, deleteThreshold,
                                                  ShowTraceMessages);
            //bestFit = _isotopeFitter.GetFitScore(peakData, chargeState, peak, record, _deleteIntensityThreshold, _minTheoreticalIntensityForScore, DebugFlag);
            //_isotopeFitter.GetZeroingMassRange(_zeroingStartMz, _zeroingStopMz, record.DeltaMz, _deleteIntensityThreshold, DebugFlag);

            if (CheckPatternsAgainstChargeOne && chargeState != 1)
            {
                HornTransformResults recordCharge1;
                int fitCountBasisCharge1;
                var bestFitCharge1 = _isotopeFitScorer.GetFitScore(peakData, 1, ref peakCharge1, out recordCharge1,
                                                                   deleteThreshold, MinIntensityForScore, LeftFitStringencyFactor,
                                                                   RightFitStringencyFactor, out fitCountBasisCharge1, ShowTraceMessages);

                //double bestFitCharge1 = _isotopeFitter.GetFitScore(peakData, 1, peakCharge1, recordCharge1, _deleteIntensityThreshold, _minTheoreticalIntensityForScore, DebugFlag);
                //_isotopeFitter.GetZeroingMassRange(_zeroingStartMz, _zeroingStopMz, record.DeltaMz, _deleteIntensityThreshold, DebugFlag);
                double startMz1 = 0;
                double stopMz1  = 0;
                _isotopeFitScorer.GetZeroingMassRange(out startMz1, out stopMz1, record.DeltaMz, deleteThreshold,
                                                      ShowTraceMessages);
                if (bestFit > MaxFitAllowed && bestFitCharge1 < MaxFitAllowed)
                {
                    bestFit        = bestFitCharge1;
                    fitCountBasis  = fitCountBasisCharge1;
                    peak           = peakCharge1;
                    record         = new HornTransformResults(recordCharge1);
                    zeroingStartMz = startMz1;
                    zeroingStopMz  = stopMz1;
                    chargeState    = 1;
                }
            }

            if (bestFit > MaxFitAllowed) // check if fit is good enough
            {
                return(false);
            }

            if (ShowTraceMessages)
            {
                Console.Error.WriteLine("\tBack with fit = " + record.Fit);
            }

            // Applications using this DLL should use Abundance instead of AbundanceInt
            record.Abundance   = peak.Intensity;
            record.ChargeState = chargeState;

            ThrashV1Peak monoPeak;
            var          monoMz = record.MonoMw / record.ChargeState + ChargeCarrierMass;

            // used when _reportO18Plus2Da is true.
            ThrashV1Peak m3Peak;
            var          monoPlus2Mz = record.MonoMw / record.ChargeState + 2.0 / record.ChargeState + ChargeCarrierMass;

            peakData.FindPeak(monoMz - peak.FWHM, monoMz + peak.FWHM, out monoPeak);
            peakData.FindPeak(monoPlus2Mz - peak.FWHM, monoPlus2Mz + peak.FWHM, out m3Peak);

            record.MonoIntensity      = (int)monoPeak.Intensity;
            record.MonoPlus2Intensity = (int)m3Peak.Intensity;
            record.SignalToNoise      = peak.SignalToNoiseDbl;
            record.FWHM      = peak.FWHM;
            record.PeakIndex = peak.PeakIndex;

            SetIsotopeDistributionToZero(peakData, peak, zeroingStartMz, zeroingStopMz, record.MonoMw, chargeState, true,
                                         record, ShowTraceMessages);
            if (ShowTraceMessages)
            {
                Console.Error.WriteLine("Performed deisotoping of " + peak.Mz);
            }
            return(true);
        }