/// <summary> /// calculates the fit score between the theoretical distribution stored and the observed data. Normalizes the observed /// intensity by specified intensity. /// </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="intensityNormalizer"> /// intensity to normalize the peaks to. assumes that if peak with intensity = normalizer was /// present, it would be normalized to 100 /// </param> /// <param name="mzDelta"> /// specifies the mass delta between theoretical and observed m/z. The we are looking to score /// against the feature in the observed data at theoeretical m/z + mzDelta /// </param> /// <param name="minIntensityForScore">minimum intensity for score</param> /// <param name="debug">prints debugging information if this is set to true.</param> public override double FitScore(PeakData peakData, int chargeState, double intensityNormalizer, double mzDelta, double minIntensityForScore, bool debug = false) { throw new Exception("Don't Ever come into this FitScore overload in PeakFit"); var numPoints = TheoreticalDistMzs.Count; if (numPoints < 3) { return(1); } double fit = 0; double sum = 0; double lastYVal = 0; double diff = 0; for (var pointNum = 0; pointNum < numPoints; pointNum++) { var mz = TheoreticalDistMzs[pointNum] + mzDelta; var theoreticalIntensity = TheoreticalDistIntensities[pointNum]; // observed intensities have to be normalized so that the maximum intensity is 100, if (theoreticalIntensity >= minIntensityForScore && diff >= 0 && theoreticalIntensity < lastYVal) { ThrashV1Peak foundPeak; var found = peakData.GetPeak(mz - 0.1, mz + 0.1, out foundPeak); if (found) { var observedIntensity = 100 * foundPeak.Intensity / intensityNormalizer; var intensityDiff = observedIntensity - theoreticalIntensity; var intensitySum = observedIntensity + theoreticalIntensity; fit += intensityDiff * intensityDiff; sum += theoreticalIntensity * theoreticalIntensity; } fit += theoreticalIntensity * theoreticalIntensity; sum += theoreticalIntensity * theoreticalIntensity; } diff = theoreticalIntensity - lastYVal; lastYVal = theoreticalIntensity; } return(fit / (sum + 0.001)); }
/// <summary> /// will calculate the delta mz (referenced to the theor) based on several of the observed peaks /// </summary> /// <param name="startingDelta"></param> /// <param name="peakWidth"></param> /// <param name="obsPeakData"></param> /// <param name="theorPeakData"></param> /// <param name="theorIntensityCutOff"></param> /// <returns></returns> public double CalculateDeltaFromSeveralObservedPeaks(double startingDelta, double peakWidth, PeakData obsPeakData, PeakData theorPeakData, double theorIntensityCutOff) { //the idea is to use a selected number of theor peaks //and for each theor peak, use the delta (mz offset) info //to find the obs peak data and determine the delta value for that peak. //accumulate delta values in an array and then calculate a weighted average var numTheorPeaks = theorPeakData.GetNumPeaks(); var filteredTheorPeakData = new PeakData(); //filter the theor list var numFilteredTheorPeaks = 0; for (var i = 0; i < numTheorPeaks; i++) { ThrashV1Peak peak; theorPeakData.GetPeak(i, out peak); if (peak.Intensity >= theorIntensityCutOff) { filteredTheorPeakData.AddPeak(peak); numFilteredTheorPeaks++; } } if (numFilteredTheorPeaks == 0) { return(startingDelta); } var deltaArray = new double[numFilteredTheorPeaks]; var intensityArray = new double[numFilteredTheorPeaks]; double intensitySum = 0; //double weightedSumOfDeltas = 0; for (var i = 0; i < numFilteredTheorPeaks; i++) { ThrashV1Peak theorPeak; filteredTheorPeakData.GetPeak(i, out theorPeak); var targetMzLower = theorPeak.Mz + startingDelta - peakWidth; var targetMzUpper = theorPeak.Mz + startingDelta + peakWidth; ThrashV1Peak foundPeak; obsPeakData.FindPeak(targetMzLower, targetMzUpper, out foundPeak); if (foundPeak.Mz > 0) { deltaArray[i] = foundPeak.Mz - theorPeak.Mz; intensityArray[i] = foundPeak.Intensity; intensitySum += foundPeak.Intensity; } else { deltaArray[i] = startingDelta; intensityArray[i] = 0; //obs peak was not found; therefore assign 0 intensity (will have no effect on delta calc) } } if (intensitySum.Equals(0)) { return(startingDelta); // no obs peaks found at all; return default } //now perform a weighted average double weightedDelta = 0; for (var i = 0; i < numFilteredTheorPeaks; i++) { weightedDelta += intensityArray[i] / intensitySum * deltaArray[i]; } return(weightedDelta); }
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); }
public void PerformTransform( float backgroundIntensity, float minPeptideIntensity, int maxProcessingTimeMinutes, ref float[] mzs, ref float[] intensities, ref ThrashV1Peak[] peaks, ref HornTransformResults[] transformResults, out bool processingAborted) { PercentDone = 0; processingAborted = false; var numPoints = mzs.Length; if (mzs.Length == 0) { return; } // mzs should be in sorted order double minMz = mzs[0]; double maxMz = mzs[numPoints - 1]; var mzList = new List <double>(mzs.Select(x => (double)x)); var intensityList = new List <double>(intensities.Select(x => (double)x)); var peakData = new PeakData(); peakData.SetPeaks(peaks); peakData.MzList = mzList; peakData.IntensityList = intensityList; if (IsMZRangeUsed) { minMz = MinMZ; maxMz = MaxMZ; } //loads 'currentPeak' with the most intense peak within minMZ and maxMZ ThrashV1Peak currentPeak; var found = peakData.GetNextPeak(minMz, maxMz, out currentPeak); //var fwhm_SN = currentPeak.FWHM; var transformRecords = new List <HornTransformResults>(); var numTotalPeaks = peakData.GetNumPeaks(); StatusMessage = "Performing Horn Transform on peaks"; var startTime = DateTime.UtcNow; while (found) { var numPeaksLeft = peakData.GetNumUnprocessedPeaks(); PercentDone = 100 * (numTotalPeaks - numPeaksLeft) / numTotalPeaks; if (PercentDone % 5 == 0) { StatusMessage = string.Concat("Done with ", Convert.ToString(numTotalPeaks - numPeaksLeft), " of ", Convert.ToString(numTotalPeaks), " peaks."); } if (currentPeak.Intensity < minPeptideIntensity) { break; } //--------------------- Transform performed ------------------------------ HornTransformResults transformRecord; var foundTransform = FindTransform(peakData, ref currentPeak, out transformRecord, backgroundIntensity); if (foundTransform && transformRecord.ChargeState <= MaxChargeAllowed) { if (IsActualMonoMZUsed) { //retrieve experimental monoisotopic peak var monoPeakIndex = transformRecord.IsotopePeakIndices[0]; ThrashV1Peak monoPeak; peakData.GetPeak(monoPeakIndex, out monoPeak); //set threshold at 20% less than the expected 'distance' to the next peak var errorThreshold = 1.003 / transformRecord.ChargeState; errorThreshold = errorThreshold - errorThreshold * 0.2; var calcMonoMz = transformRecord.MonoMw / transformRecord.ChargeState + 1.00727638; if (Math.Abs(calcMonoMz - monoPeak.Mz) < errorThreshold) { transformRecord.MonoMw = monoPeak.Mz * transformRecord.ChargeState - 1.00727638 * transformRecord.ChargeState; } } transformRecords.Add(transformRecord); } if (DateTime.UtcNow.Subtract(startTime).TotalMinutes > maxProcessingTimeMinutes) { processingAborted = true; found = false; } else { found = peakData.GetNextPeak(minMz, maxMz, out currentPeak); } } PercentDone = 100; // Done with the transform. Lets copy them all to the given memory structure. //Console.WriteLine("Done with Mass Transform. Found " + transformRecords.Count + " features"); transformResults = transformRecords.ToArray(); PercentDone = 100; }
public virtual bool FindTransform(PeakData peakData, ref clsPeak peak, out clsHornTransformResults record, double backgroundIntensity = 0) { record = new clsHornTransformResults(); if (peak.SignalToNoise < TransformParameters.MinS2N || peak.FWHM.Equals(0)) { return(false); } //var resolution = peak.Mz / peak.FWHM; var chargeState = AutoCorrelationChargeDetermination.GetChargeState(peak, peakData, DebugFlag); if (chargeState == -1 && TransformParameters.CheckAllPatternsAgainstCharge1) { chargeState = 1; } if (DebugFlag) { Console.Error.WriteLine("Deisotoping :" + peak.Mz); Console.Error.WriteLine("Charge = " + chargeState); } if (chargeState == -1) { return(false); } if ((peak.Mz + TransformParameters.CCMass) * chargeState > TransformParameters.MaxMW) { return(false); } if (TransformParameters.O16O18Media) { 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; clsPeak 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 clsPeak(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 = TransformParameters.DeleteIntensityThreshold; int fitCountBasis; var bestFit = TransformParameters.IsotopeFitScorer.GetFitScore(peakData, chargeState, ref peak, out record, deleteThreshold, TransformParameters.MinIntensityForScore, TransformParameters.LeftFitStringencyFactor, TransformParameters.RightFitStringencyFactor, out fitCountBasis, DebugFlag); // 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; TransformParameters.IsotopeFitScorer.GetZeroingMassRange(out zeroingStartMz, out zeroingStopMz, record.DeltaMz, deleteThreshold, DebugFlag); //bestFit = _isotopeFitter.GetFitScore(peakData, chargeState, peak, record, _deleteIntensityThreshold, _minTheoreticalIntensityForScore, DebugFlag); //_isotopeFitter.GetZeroingMassRange(_zeroingStartMz, _zeroingStopMz, record.DeltaMz, _deleteIntensityThreshold, DebugFlag); if (TransformParameters.CheckAllPatternsAgainstCharge1 && chargeState != 1) { clsHornTransformResults recordCharge1; int fitCountBasisCharge1; var bestFitCharge1 = TransformParameters.IsotopeFitScorer.GetFitScore(peakData, 1, ref peakCharge1, out recordCharge1, deleteThreshold, TransformParameters.MinIntensityForScore, TransformParameters.LeftFitStringencyFactor, TransformParameters.RightFitStringencyFactor, out fitCountBasisCharge1, DebugFlag); //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; TransformParameters.IsotopeFitScorer.GetZeroingMassRange(out startMz1, out stopMz1, record.DeltaMz, deleteThreshold, DebugFlag); if (bestFit > TransformParameters.MaxFit && bestFitCharge1 < TransformParameters.MaxFit) { bestFit = bestFitCharge1; fitCountBasis = fitCountBasisCharge1; peak = peakCharge1; record = new clsHornTransformResults(recordCharge1); zeroingStartMz = startMz1; zeroingStopMz = stopMz1; chargeState = 1; } } if (bestFit > TransformParameters.MaxFit) // check if fit is good enough { return(false); } if (DebugFlag) { 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; clsPeak monoPeak; var monoMz = record.MonoMw / record.ChargeState + TransformParameters.CCMass; // used when _reportO18Plus2Da is true. clsPeak m3Peak; var monoPlus2Mz = record.MonoMw / record.ChargeState + 2.0 / record.ChargeState + TransformParameters.CCMass; 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.SignalToNoise; record.FWHM = peak.FWHM; record.PeakIndex = peak.PeakIndex; SetIsotopeDistributionToZero(peakData, peak, zeroingStartMz, zeroingStopMz, record.MonoMw, chargeState, true, record, DebugFlag); if (DebugFlag) { Console.Error.WriteLine("Performed deisotoping of " + peak.Mz); } return(true); }