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); }
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); }