/// <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) { var numPoints = TheoreticalDistMzs.Count; if (numPoints < 3) { return(1); } double fit = 0; double sum = 0; for (var pointNum = 0; pointNum < numPoints; pointNum++) { var mz = TheoreticalDistMzs[pointNum] + mzDelta; var theoreticalIntensity = TheoreticalDistIntensities[pointNum]; if (theoreticalIntensity >= minIntensityForScore) { // observed intensities have to be normalized so that the maximum intensity is 100, // like that for theoretical intensities. var observedIntensity = 100 * GetPointIntensity(mz, peakData.MzList, peakData.IntensityList) / intensityNormalizer; var intensityDiff = observedIntensity - theoreticalIntensity; var intensitySum = observedIntensity + theoreticalIntensity; fit += intensityDiff * intensityDiff / intensitySum; sum += theoreticalIntensity * observedIntensity; } } return(fit / (sum + 0.001)); }
public string ToXML(FAIMStoMzXMLProcessor processor) { // place scan byte depth into our tracking list var index = new Index(processor.ByteTracking.CurrentScan, processor.ByteTracking.ByteDepth + 3); processor.ByteTracking.ScanOffsets.Add(index); FilterLine = FixFilterLine(); var sb = new StringBuilder(); sb.AppendFormat(" <scan num=\"{0}\"", processor.ByteTracking.CurrentScan).AppendLine(); sb.AppendFormat(" msLevel=\"{0}\"", MsLevel).AppendLine(); sb.AppendFormat(" peaksCount=\"{0}\"", PeaksCount).AppendLine(); sb.AppendFormat(" polarity=\"{0}\"", Polarity).AppendLine(); sb.AppendFormat(" scanType=\"{0}\"", ScanType).AppendLine(); sb.AppendFormat(" filterLine=\"{0}\"", FilterLine).AppendLine(); sb.AppendFormat(" retentionTime=\"{0}\"", RetentionTime).AppendLine(); sb.AppendFormat(" lowMz=\"" + Math.Round(LowMz, 3) + "\"").AppendLine(); sb.AppendFormat(" highMz=\"" + Math.Round(HighMz, 3) + "\"").AppendLine(); sb.AppendFormat(" basePeakMz=\"" + Math.Round(BasePeakMz, 3) + "\"").AppendLine(); sb.AppendFormat(" basePeakIntensity=\"" + FormatSpecialNumber(BasePeakIntensity) + "\"").AppendLine(); sb.AppendFormat(" totIonCurrent=\"" + FormatSpecialNumber(TotIonCurrent) + "\"").AppendLine(); sb.AppendFormat(" collisionEnergy=\"" + CollisionEnergy + "\">").AppendLine(); sb.AppendLine(PrecursorMz.ToXML()); sb.AppendLine(PeakData.ToXML(4)); sb.Append(" </scan>"); processor.ByteTracking.CurrentScan++; return(sb.ToString()); }
private static IList<PeakData> ImportFile(TextReader peakViewReader) { var peakDatas = new List<PeakData>(); var msFileNames = new List<string>(); var fileReader = new DsvFileReader(peakViewReader, TextUtil.SEPARATOR_TSV); Debug.Assert(Equals(fileReader.GetFieldIndex(PROTEIN), 0)); Debug.Assert(Equals(fileReader.GetFieldIndex(PEPTIDE), 1)); Debug.Assert(Equals(fileReader.GetFieldIndex(LABEL), 2)); Debug.Assert(Equals(fileReader.GetFieldIndex(PRECURSOR), 3)); Debug.Assert(Equals(fileReader.GetFieldIndex(CHARGE), 4)); Debug.Assert(Equals(fileReader.GetFieldIndex(RT), 5)); Debug.Assert(Equals(fileReader.GetFieldIndex(DECOY), 6)); for (int i = 7; i < fileReader.NumberOfFields; ++i) { msFileNames.Add(fileReader.FieldNames[i]); } while (fileReader.ReadLine() != null) { string modifiedSequence = fileReader.GetFieldByName(PEPTIDE); string decoyString = fileReader.GetFieldByName(DECOY); bool decoy; var hasDecoyValue = bool.TryParse(decoyString, out decoy); Debug.Assert(hasDecoyValue); foreach (var msFileName in msFileNames) { string dataFieldString = fileReader.GetFieldByName(msFileName); double dataField; var hasDataFieldValue = double.TryParse(dataFieldString, out dataField); Debug.Assert(hasDataFieldValue); var peakData = new PeakData(dataField, modifiedSequence, msFileName, decoy); peakDatas.Add(peakData); } } return peakDatas; }
public IList <PeakData> ImportFile(TextReader peakViewReader) { var peakDatas = new List <PeakData>(); var msFileNames = new List <string>(); var fileReader = new DsvFileReader(peakViewReader, TextUtil.SEPARATOR_TSV); Assert.AreEqual(fileReader.GetFieldIndex(PROTEIN), 0); Assert.AreEqual(fileReader.GetFieldIndex(PEPTIDE), 1); Assert.AreEqual(fileReader.GetFieldIndex(LABEL), 2); Assert.AreEqual(fileReader.GetFieldIndex(PRECURSOR), 3); Assert.AreEqual(fileReader.GetFieldIndex(CHARGE), 4); Assert.AreEqual(fileReader.GetFieldIndex(RT), 5); Assert.AreEqual(fileReader.GetFieldIndex(DECOY), 6); for (int i = 7; i < fileReader.NumberOfFields; ++i) { msFileNames.Add(fileReader.FieldNames[i]); } while (fileReader.ReadLine() != null) { string modifiedSequence = fileReader.GetFieldByName(PEPTIDE); string decoyString = fileReader.GetFieldByName(DECOY); bool decoy; Assert.IsTrue(bool.TryParse(decoyString, out decoy)); foreach (var msFileName in msFileNames) { string dataFieldString = fileReader.GetFieldByName(msFileName); double dataField; Assert.IsTrue(double.TryParse(dataFieldString, out dataField)); var peakData = new PeakData(dataField, modifiedSequence, msFileName, decoy); peakDatas.Add(peakData); } } return(peakDatas); }
internal static void SetPeaks(ref PeakData peakData, ref clsPeak[] peaks) { foreach (var pk in peaks) { peakData.AddPeak(new clsPeak(pk)); } peakData.InitializeUnprocessedPeakData(); }
/// <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="peak"> peak for which we want to compute the fit function.</param> /// <param name="mzDelta">specifies the mass delta between theoretical and observed m/z with the best fit so far.</param> /// <param name="minIntensityForScore">minimum intensity for score</param> /// <param name="pointsUsed">number of points used</param> /// <param name="debug">debug output flag</param> public override double FitScore(PeakData peakData, int chargeState, ThrashV1Peak peak, double mzDelta, double minIntensityForScore, out int pointsUsed, bool debug = false) { pointsUsed = 0; var numPoints = TheoreticalDistMzs.Count; if (numPoints < 3) { return(1); } if (peak.Intensity <= 0) { return(1); } var maxObservedIntensity = peak.Intensity; if (maxObservedIntensity <= 0) { Console.Error.WriteLine("Peak intensity was <=0 during FitScore. mz = " + peak.Mz + " , intensity = " + peak.Intensity); Environment.Exit(1); } double fit = 0; double sum = 0; for (var pointNum = 0; pointNum < numPoints; pointNum++) { var mz = TheoreticalDistMzs[pointNum] + mzDelta; var theoreticalIntensity = (float)TheoreticalDistIntensities[pointNum]; if (theoreticalIntensity >= minIntensityForScore) { // observed intensities have to be normalized so that the maximum intensity is 100, // like that for theoretical intensities. var observedIntensity = 100 * GetPointIntensity(mz, peakData.MzList, peakData.IntensityList) / maxObservedIntensity; var intensityDiff = observedIntensity - theoreticalIntensity; fit += intensityDiff * intensityDiff; sum += theoreticalIntensity * theoreticalIntensity; pointsUsed++; } } return(fit / (sum + 0.001)); }
// for outputting valid MzXML strings to file public string ToXML(FAIMStoMzXMLProcessor processor) { // place scan byte depth into our tracking list var index = new Index(processor.ByteTracking.CurrentScan, processor.ByteTracking.ByteDepth + 2); processor.ByteTracking.ScanOffsets.Add(index); FilterLine = FixFilterLine(); var sb = new StringBuilder(); sb.AppendFormat(" <scan num=\"{0}\"", processor.ByteTracking.CurrentScan).AppendLine(); sb.AppendFormat(" msLevel=\"{0}\"", MsLevel).AppendLine(); sb.AppendFormat(" peaksCount=\"{0}\"", PeaksCount).AppendLine(); sb.AppendFormat(" polarity=\"{0}\"", Polarity).AppendLine(); sb.AppendFormat(" scanType=\"{0}\"", ScanType).AppendLine(); sb.AppendFormat(" filterLine=\"{0}\"", FilterLine).AppendLine(); sb.AppendFormat(" retentionTime=\"{0}\"", RetentionTime).AppendLine(); sb.AppendFormat(" lowMz=\"" + Math.Round(LowMz, 3) + "\"").AppendLine(); sb.AppendFormat(" highMz=\"" + Math.Round(HighMz, 3) + "\"").AppendLine(); sb.AppendFormat(" basePeakMz=\"" + Math.Round(BasePeakMz, 3) + "\"").AppendLine(); sb.AppendFormat(" basePeakIntensity=\"" + FormatSpecialNumber(BasePeakIntensity) + "\"").AppendLine(); sb.AppendFormat(" totIonCurrent=\"" + FormatSpecialNumber(TotIonCurrent) + "\">").AppendLine(); sb.AppendLine(PeakData.ToXML(3)); // advance the byteTracker for Ms2 Indices processor.ByteTracker(sb.ToString(), true); processor.ByteTracking.CurrentScan++; foreach (var ms2 in Ms2s) { var ms2String = ms2.ToXML(processor); sb.AppendLine(ms2String); // advance byteTracker for the Ms2 Entry processor.ByteTracker(ms2String); } sb.Append(" </scan>"); processor.ByteTracker(" </scan>"); return(sb.ToString()); }
/// <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> /// 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) * { * clsPeak 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); */ }
/*[gord] the following is currently unused. The idea was to give weighting to the algorithm so that * the user could favor certain fitting parameters (i.e. space between isotopomers) over others * public double FindIsotopicDist(PeakProcessing.PeakData peakData, int cs, PeakProcessing.Peak peak, * IsotopeFitRecord isoRecord, double deleteIntensityThreshold, double spacingWeight, double spacingVar, * double signalToNoiseWeight, double signalToNoiseThresh, double ratioWeight, double ratioThreshold, * double fitWeight, double fitThreshold, bool debug = false) * { * if (cs <= 0) * { * Environment.Exit(1); * } * * //Get theoretical distribution using Mercury algorithm * double peakMass = (peak.mdbl_mz - ChargeCarrierMass) * cs; * double resolution = peak.mdbl_mz / peak.mdbl_FWHM; * GetIsotopeDistribution(peakMass, cs, resolution, out TheoreticalDistMzs, * out TheoreticalDistIntensities, * deleteIntensityThreshold, debug); * * double theorMostAbundantPeakMz = IsotopeDistribution.mdbl_max_peak_mz; * double delta = peak.mdbl_mz - theorMostAbundantPeakMz; * double spacingScore = 0; * double signalToNoiseScore = 0; * double ratioScore = 0; * double totalScore = 0; * double maximumScore = spacingWeight + signalToNoiseWeight + ratioWeight + fitWeight; * * //this will select peaks to the left until * for (double dd = 1.003 / cs; dd <= 10.03 / cs; dd += 1.003 / cs) * { * double theorLeftPeakMz = 0; * double theorLeftPeakIntensity = 0; * PeakProcessing.Peak leftPeak; * peakData.FindPeak(peak.mdbl_mz - dd - peak.mdbl_FWHM, peak.mdbl_mz - dd + peak.mdbl_FWHM, out leftPeak); * //PeakProcessing.FindPeak * IsotopeDistribution.FindPeak(theorMostAbundantPeakMz - dd - 0.2 / cs, * theorMostAbundantPeakMz - dd + 0.2 / cs, out theorLeftPeakMz, out theorLeftPeakIntensity); * * if (leftPeak.mdbl_mz > 0) //if there is an experimental peak... * { * //get spacing score * spacingScore = spacingWeight * 1; * * //get S/N score * if (leftPeak.mdbl_SN > signalToNoiseThresh) * { * signalToNoiseScore = signalToNoiseWeight * 1; * } * * //get Ratio score * double leftPeakRatio = leftPeak.mdbl_intensity / peak.mdbl_intensity; * double theorLeftPeakRatio = theorLeftPeakIntensity / 1; * //TODO: need to check if this most abundant theor peak's intensity is 1 * } * * //get Ratio score * } * //get S/N score * //get Fit score * //calculate maximum score * //get overall score * return 0; * }*/ public PeakData GetTheoreticalIsotopicDistributionPeakList(List <double> xvals, List <double> yvals) { var peakList = new PeakData(); var processor = new PeakProcessor(); processor.SetOptions(0.5, 1, false, PeakFitType.Apex); processor.DiscoverPeaks(xvals, yvals, 0, 10000); var numpeaks = processor.PeakData.GetNumPeaks(); for (var i = 0; i < numpeaks; i++) { ThrashV1Peak peak; processor.PeakData.GetPeak(i, out peak); peakList.AddPeak(peak); } return(peakList); }
/// <summary> /// calculates the fit score for a peak against a molecular formula. /// </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="formula">stores the formula we want to 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="debug">if debugging output is enabled</param> public double GetFitScore(PeakData peakData, int chargeState, ThrashV1Peak peak, MolecularFormula formula, double deleteIntensityThreshold, double minTheoreticalIntensityForScore, bool debug = false) { if (chargeState <= 0) { Console.WriteLine("Negative value for charge state. " + chargeState); Environment.Exit(1); } if (debug) { Console.WriteLine("Getting isotope distribution for formula = " + formula + " mz = " + peak.Mz + " charge = " + chargeState); } var resolution = peak.Mz / peak.FWHM; IsotopeDistribution.ChargeCarrierMass = ChargeCarrierMass; IsotopeDistribution.ApType = ApodizationType.Gaussian; TheoreticalDistIntensities.Clear(); TheoreticalDistMzs.Clear(); IsotopeDistribution.CalculateDistribution(chargeState, resolution, formula, out TheoreticalDistMzs, out TheoreticalDistIntensities, deleteIntensityThreshold, out IsotopeMzs, out IsotopeIntensities, debug); var delta = peak.Mz - IsotopeDistribution.MaxPeakMz; if (debug) { Console.WriteLine("Going for first fit"); } int pointsUsed; return(FitScore(peakData, chargeState, peak, delta, minTheoreticalIntensityForScore, out pointsUsed, debug)); }
/// <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="peak"> peak for which we want to compute the fit function.</param> /// <param name="mzDelta">specifies the mass delta between theoretical and observed m/z with the best fit so far.</param> /// <param name="minIntensityForScore">minimum intensity for score</param> /// <param name="pointsUsed">number of points used</param> /// <param name="debug">debug output flag</param> public abstract double FitScore(PeakData peakData, int chargeState, ThrashV1Peak peak, double mzDelta, double minIntensityForScore, out int pointsUsed, bool debug = false);
/// <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); }
/// <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); }
/// <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="normalizer"> /// 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 + mz_delta /// </param> /// <param name="minIntensityForScore">minimum intensity for score</param> /// <param name="debug">prints debugging information if this is set to true.</param> public abstract double FitScore(PeakData peakData, int chargeState, double normalizer, double mzDelta, double minIntensityForScore, bool debug = false);
static void Main(string[] args) { // *** CHANGE TO THE IP ADDRESS FOR INSTRUMENT *** string instrumentIpAddress = "192.168.86.70"; // Create a TCP client for communicating with the Hyperion instrument TcpClient tcpClient = new TcpClient(); // Connect to the instrument over TCP/IP tcpClient.Connect(instrumentIpAddress, Command.TcpPort); NetworkStream tcpNetworkStream = tcpClient.GetStream(); // Execute a simple command to retrieve the instrument serial number CommandResponse response = Command.Execute( tcpNetworkStream, CommandName.GetSerialNumber); // The response (unless specifically suppressed) contains an ASCII based Message field // AND a binary (byte[]) Content field. The ASCII field is intended to be human readable // and the binary data is intended to be easily parsed by a computer. WriteLine("Instrument Serial Number"); WriteLine("------------------------"); WriteLine($"Message: {response.Message}"); WriteLine($"Content Converted to String {response.AsString()}"); WriteLine(); WriteLine(); // Execute the #GetPeaks command. The CommandName contains static string members // for commands exposed by the instrument. response = Command.Execute( tcpNetworkStream, CommandName.GetPeaks); // Several extension methods are defined in the communication library that // easily convert the response from a byte[] to useful types such as // int, double, and more complex responses such as Peak/Spectrum data PeakData peakData = response.AsPeakData(); WriteLine("Peak Data Header"); WriteLine("---------------------"); WriteLine($"Serial Number: {peakData.SerialNumber}"); WriteLine($"Timestamp: {peakData.Timestamp}"); WriteLine(); WriteLine("Peaks"); WriteLine("-----"); // The PeakData exposes the peaks in two ways...as Arrays and as Enumerables. The // arrays will allocate new memory for the data but can be advantageous if the // data needs to be repeatedly accessed. The Enumerable is great for situations where // the data needs to be simply iterated through once and processed. This provides very // high performance and low overhead for situations such as streaming large number of // peaks at very high speeds. for (int channelIndex = 0; channelIndex < 4; channelIndex++) { WriteLine($"Channel {channelIndex}: "); foreach (double wavelength in peakData.AsEnumerable(1)) { WriteLine($"\t{wavelength} nm"); } } WriteLine(); WriteLine(); // Retrieve the optical full spectrum response response = Command.Execute(tcpNetworkStream, CommandOptions.None, CommandName.GetSpectrum); // Use the extension methods to easily obtain the spectrum data SpectrumData spectrumData = response.AsSpectrumData(); WriteLine("Full Spectrum"); WriteLine("-------------"); WriteLine($"Wavelength Start: {spectrumData.WavelengthStart:F3} nm"); WriteLine($"Wavelength Step: {(int)(1000 * spectrumData.WavelengthStep)} pm"); WriteLine($"Wavelength Step Count: {spectrumData.WavelengthStepCount}"); WriteLine($"Channel Count: {spectrumData.ChannelCount}"); WriteLine($"Serial Number: {spectrumData.SerialNumber}"); WriteLine($"Timestamp: {spectrumData.Timestamp}"); WriteLine(); WriteLine(); // Remove existing sensors response = Command.Execute(tcpNetworkStream, CommandOptions.None, CommandName.GetSensorNames); string[] sensorNames = response.AsString().Split(' '); foreach (string sensorName in sensorNames) { WriteLine($"Removing sensor: {sensorName}"); response = Command.Execute(tcpNetworkStream, CommandOptions.None, CommandName.RemoveSensor, sensorName); } // Add some sensors for (int i = 1; i <= 20; i++) { string name = $"sensor_{i}"; string model = i % 2 == 1 ? "os7510" : "os7520"; int channel = (i - 1) % 4 + 1; int wavelength = 1510 + ((i - 1) % 4) * 20; bool fixedOrientation = i % 2 == 0; double calibration = 10.0 * i; WriteLine($"Adding Sensor {name}"); WriteLine("----------------------------------------"); WriteLine($"Model: {model}"); WriteLine($"Channel: {channel}"); WriteLine($"Wavelength Band: {wavelength} nm"); WriteLine($"Calibration Factor: {calibration} nm/g"); WriteLine($"Fixed Orientation: {fixedOrientation}"); WriteLine(); string[] input_args = { name, model, channel.ToString(), "0", wavelength.ToString(), calibration.ToString(), fixedOrientation.ToString() }; response = Command.Execute(tcpNetworkStream, CommandOptions.None, CommandName.AddSensor, input_args); } // Retrieve the defined Sensors response = Command.Execute(tcpNetworkStream, CommandOptions.None, CommandName.ExportSensors); WriteLine(response.Message); int offset = 0; int version = BitConverter.ToUInt16(response.Content, offset); offset += sizeof(UInt16); int numberOfSensors = BitConverter.ToUInt16(response.Content, offset); offset += sizeof(UInt16); // Sensor Count WriteLine($"Sensors - {numberOfSensors} (Data Export Version = {version})"); WriteLine(); // Create sensors for (int sensorIndex = 0; sensorIndex < numberOfSensors; sensorIndex++) { FabryPerotAccelerometer fpSensor = (FabryPerotAccelerometer)SensorBase.Create(response.Content, ref offset); WriteLine($"Sensor {sensorIndex + 1} - {fpSensor.Name} ({fpSensor.Model})"); WriteLine($"Sensor Definition Version: {fpSensor.FPSesnorVersion}"); WriteLine("----------------------------------------"); WriteLine($"ID: {fpSensor.Id}"); WriteLine($"Model: {fpSensor.Model}"); WriteLine($"Channel: {fpSensor.DutChannelIndex + 1}"); WriteLine($"Wavelength Band: {fpSensor.WavelengthBand} nm"); WriteLine($"Calibration Factor: {fpSensor.CalibrationFactor} nm/g"); WriteLine($"Fixed Orientation: {fpSensor.FixedOrientation}"); WriteLine(); } WriteLine(); // Cleanup by closing the TCP connection tcpNetworkStream.Close(); tcpClient.Close(); // Now demonstrating using the data streaming to continuously read consecutive // peak data sets. tcpClient = new TcpClient(); tcpClient.Connect(instrumentIpAddress, StreamingDataReader.PeakTcpPort); tcpNetworkStream = tcpClient.GetStream(); // The StreamingDataReader class works for peaks and full spectrum. It can be // used to easily and efficiently read consecutive datasets. The class internally // uses a single buffer of memory to avoid allocating and collecting large // amounts of memory and system resources. The mode Peak, Spectrum, Sensor) is // defined when the reader is created. StreamingDataReader reader = new StreamingDataReader(StreamingDataMode.Peaks); WriteLine("Streaming Peak Data Acquistion Serial Numbers"); WriteLine("---------------------------------------------"); for (int index = 0; index < 10; index++) { WriteLine( $"{index}: " + $"{ reader.ReadStreamingData(tcpNetworkStream).AsPeakData().SerialNumber}"); } WriteLine(); tcpNetworkStream.Close(); tcpClient.Close(); // Now demonstrating using the data streaming to continuously read consecutive // sensor data sets. tcpClient = new TcpClient(); tcpClient.Connect(instrumentIpAddress, StreamingDataReader.SensorTcpPort); tcpNetworkStream = tcpClient.GetStream(); // The StreamingDataReader class works for peaks, full spectrum and sensors. It can be // used to easily and efficiently read consecutive datasets. The class internally // uses a single buffer of memory to avoid allocating and collecting large // amounts of memory and system resources. The mode Peak, Spectrum, Sensor) is // defined when the reader is created. StreamingDataReader sensorReader = new StreamingDataReader(StreamingDataMode.Sensor); WriteLine("Streaming Sensor Data Acquistion Serial Numbers"); WriteLine("---------------------------------------------"); for (int index = 0; index < 10; index++) { SensorData sensorData = sensorReader.ReadStreamingData(tcpNetworkStream).AsSensorData(); WriteLine( $"{index}: " + $"{sensorData.SerialNumber}"); } WriteLine(); tcpNetworkStream.Close(); tcpClient.Close(); // Wait for any key press to exit ReadLine(); }
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 "); } }
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; }
/// <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="peak"> peak for which we want to compute the fit function.</param> /// <param name="mzDelta">specifies the mass delta between theoretical and observed m/z with the best fit so far.</param> /// <param name="minIntensityForScore">minimum intensity for score</param> /// <param name="pointsUsed">number of points used</param> /// <param name="debug">debug output flag</param> public override double FitScore(PeakData peakData, int chargeState, ThrashV1Peak peak, double mzDelta, double minIntensityForScore, out int pointsUsed, bool debug = false) { pointsUsed = 0; 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) { var found = false; ThrashV1Peak foundPeak; // remember you might be searching for the current peak (which has already been // taken out of the list of peaks. So first check it. if (Math.Abs(peak.Mz - mz) < 2 * peak.FWHM) { found = true; foundPeak = peak; } else { peakData.FindPeak(mz - peak.FWHM, mz + peak.FWHM, out foundPeak); if (foundPeak.Mz > 0) { found = true; } } if (found) { var observedIntensity = 100 * foundPeak.Intensity / peak.Intensity; var intensityDiff = observedIntensity - theoreticalIntensity; var intensityAvg = (observedIntensity + theoreticalIntensity) / 2; fit += intensityDiff * intensityDiff; sum += intensityAvg * intensityAvg; } else { fit += theoreticalIntensity * theoreticalIntensity; sum += theoreticalIntensity * theoreticalIntensity; } pointsUsed++; } diff = theoreticalIntensity - lastYVal; lastYVal = theoreticalIntensity; } return(fit / (sum + 0.001)); }
/// <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 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); }