/// <summary> /// The input UIMF file needs to be a UIMF file created by direct-injection /// IMS, with different drift tube voltages at different frames. /// This constructor intelligently group voltages together by observing /// sharp changes in running voltage standard deviation. The entire mobility /// and frame range would be accumulated. /// </summary> /// <param name="startScan"> /// The start scan. /// </param> /// <param name="endScan"> /// The end scan. /// </param> /// <param name="startBin"> /// The start bin. /// </param> /// <param name="endBin"> /// The end bin. /// </param> /// <param name="xCompression"> /// The x compression. /// </param> /// <param name="yCompression"> /// The y compression. /// </param> /// <param name="fullScan"> /// The full Scan. /// </param> /// <param name="exportFormat"> /// The export Format. /// </param> /// <returns> /// The <see cref="bool"/>. /// </returns> private bool RunVoltageAccumulationWorkflow(int startScan, int endScan, int startBin, int endBin, double xCompression, double yCompression, bool fullScan, FileFormatEnum exportFormat) { CrossSectionSearchParameters defaultParams = new CrossSectionSearchParameters(88); VoltageSeparatedAccumulatedXiCs accumulatedXiCs = new VoltageSeparatedAccumulatedXiCs(this.UimfReader, 100, defaultParams.MzWindowHalfWidthInPpm, defaultParams.DriftTubeLengthInCm); IEnumerable<VoltageGroup> voltageGroups = accumulatedXiCs.Keys; bool success = true; foreach (var voltageGroup in voltageGroups) { // convert to MzML or UIMFs if (exportFormat == FileFormatEnum.UIMF) { string outputPath = Path.Combine(this.OutputDir, this.datasetName + "_" + Math.Round(voltageGroup.MeanVoltageInVolts) + "V.uimf"); UimfExporter uimfExporter = new UimfExporter(); success = success && uimfExporter.ExportVoltageGroupAsSingleFrameUimf(outputPath, voltageGroup, this.UimfReader, this.averageNotSum, startScan, endScan, startBin, endBin, xCompression, yCompression, fullScan); Console.WriteLine("Writing UIMF files to {0}", outputPath); } else if (exportFormat == FileFormatEnum.MzML) { string outputPath = Path.Combine(this.OutputDir, this.datasetName + "_" + Math.Round(voltageGroup.MeanVoltageInVolts) + "V.mzML"); RetentionMobilitySwappedMzMLExporter mzMLExporter = new RetentionMobilitySwappedMzMLExporter(); success = success && mzMLExporter.ExportMzML(this.inputPath, outputPath, voltageGroup, this.UimfReader, this.averageNotSum); Console.WriteLine("Writing MzML files to {0}", outputPath); } } return success; }
/// <summary> /// The run libray match workflow. /// </summary> /// <param name="target"> /// The Target. /// </param> /// <returns> /// The <see cref="LibraryMatchResult"/>. /// </returns> private LibraryMatchResult RunLibrayMatchWorkflow(DriftTimeTarget target) { Trace.WriteLine(" Target: " + target.CorrespondingChemical); Trace.WriteLine(" Target Info: " + target.TargetDescriptor); // Generate Theoretical Isotopic Profile List<Peak> theoreticalIsotopicProfilePeakList = null; string empiricalFormula = target.CompositionWithAdduct.ToPlainString(); ITheorFeatureGenerator featureGenerator = new JoshTheorFeatureGenerator(); IsotopicProfile theoreticalIsotopicProfile = featureGenerator.GenerateTheorProfile(empiricalFormula, 1); theoreticalIsotopicProfilePeakList = theoreticalIsotopicProfile.Peaklist.Cast<Peak>().ToList(); // Voltage grouping VoltageSeparatedAccumulatedXiCs accumulatedXiCs = new VoltageSeparatedAccumulatedXiCs(this.uimfReader, target.MassWithAdduct, this.Parameters.InitialSearchMassToleranceInPpm, target.NormalizedDriftTimeInMs, this.Parameters.DriftTimeToleranceInMs, this.Parameters.DriftTubeLengthInCm); foreach (VoltageGroup voltageGroup in accumulatedXiCs.Keys) { // TODO Verify the temperature, pressure and drift tube voltage of the voltage group // Because we don't record TVP info in the AMT library. we can't verify it yet, so stick with last voltage group. if (IMSUtil.IsLastVoltageGroup(voltageGroup, this.NumberOfFrames)) { double globalMaxIntensity = IMSUtil.MaxIntensityAfterFrameAccumulation(voltageGroup, this.uimfReader); Trace.WriteLine(string.Format(" Temperature/Pressure/Voltage Adjusted Drift time: {0:F4} ms", IMSUtil.DeNormalizeDriftTime(target.NormalizedDriftTimeInMs, voltageGroup))); // Find peaks using multidimensional peak finder. List<IntensityPoint> intensityPoints = accumulatedXiCs[voltageGroup].IntensityPoints; List<FeatureBlob> featureBlobs = PeakFinding.FindPeakUsingWatershed(intensityPoints, this.smoother, this.Parameters.FeatureFilterLevel); List<StandardImsPeak> standardPeaks = featureBlobs.Select(featureBlob => new StandardImsPeak(featureBlob, this.uimfReader, voltageGroup, target.MassWithAdduct, this.Parameters.InitialSearchMassToleranceInPpm)).ToList(); // Score features IDictionary<StandardImsPeak, PeakScores> scoresTable = new Dictionary<StandardImsPeak, PeakScores>(); Trace.WriteLine(string.Format(" Voltage Group: {0:F4} V, [{1}-{2}]", voltageGroup.MeanVoltageInVolts, voltageGroup.FirstFrameNumber, voltageGroup.LastFrameNumber)); foreach (StandardImsPeak peak in standardPeaks) { PeakScores currentStatistics = FeatureScoreUtilities.ScoreFeature( peak, globalMaxIntensity, this.uimfReader, this.Parameters.InitialSearchMassToleranceInPpm, this.Parameters.DriftTimeToleranceInMs, voltageGroup, this.NumberOfScans, target, IsotopicScoreMethod.Angle, theoreticalIsotopicProfilePeakList); scoresTable.Add(peak, currentStatistics); } // filter out features with Ims scans at 1% left or right. Predicate<StandardImsPeak> scanPredicate = blob => FeatureFilters.FilterExtremeDriftTime(blob, (int)this.NumberOfScans); Predicate<StandardImsPeak> shapeThreshold = blob => FeatureFilters.FilterBadPeakShape(blob, scoresTable[blob].PeakShapeScore, this.Parameters.PeakShapeThreshold); Predicate<StandardImsPeak> isotopeThreshold = blob => FeatureFilters.FilterBadIsotopicProfile(blob, scoresTable[blob].IsotopicScore, this.Parameters.IsotopicThreshold); Predicate<StandardImsPeak> massDistanceThreshold = blob => FeatureFilters.FilterHighMzDistance(blob, target, this.Parameters.MatchingMassToleranceInPpm); // Print out candidate features that pass the intensity threshold. foreach (StandardImsPeak peak in standardPeaks) { DriftTimeFeatureDistance distance = new DriftTimeFeatureDistance(target, peak, voltageGroup); bool badScanRange = scanPredicate(peak); bool badPeakShape = shapeThreshold(peak); bool lowIsotopicAffinity = isotopeThreshold(peak); bool lowMzAffinity = massDistanceThreshold(peak); PeakScores currentStatistics = scoresTable[peak]; Trace.WriteLine(string.Empty); Trace.WriteLine(string.Format(" Candidate feature found at drift time {0:F2} ms (scan number {1})", peak.PeakApex.DriftTimeCenterInMs, peak.PeakApex.DriftTimeCenterInScanNumber)); Trace.WriteLine( string.Format( " M/Z: {0:F2} Dalton", peak.PeakApex.MzCenterInDalton)); Trace.WriteLine( string.Format( " Drift time: {0:F2} ms (scan number {1})", peak.PeakApex.DriftTimeCenterInMs, peak.PeakApex.DriftTimeCenterInScanNumber)); Trace.WriteLine( string.Format(" MzInDalton difference: {0:F2} ppm", distance.MassDifferenceInPpm)); Trace.WriteLine( string.Format(" Drift time difference: {0:F4} ms", distance.DriftTimeDifferenceInMs)); Trace.WriteLine(string.Format(" Intensity Score: {0:F4}", currentStatistics.IntensityScore)); Trace.WriteLine(string.Format(" Peak Shape Score: {0:F4}", currentStatistics.PeakShapeScore)); Trace.WriteLine(string.Format(" Isotopic Score: {0:F4}", currentStatistics.IsotopicScore)); Trace.WriteLine(string.Format(" AveragedPeakIntensities: {0:F4}", peak.SummedIntensities)); string rejectionReason = badScanRange ? " [Bad scan range] " : " "; rejectionReason += badPeakShape ? "[Bad Peak Shape] " : string.Empty; rejectionReason += lowMzAffinity ? "[Inaccurate Mass] " : string.Empty; rejectionReason += lowIsotopicAffinity ? "[Different Isotopic Profile] " : string.Empty; if (badScanRange || lowIsotopicAffinity || badPeakShape) { Trace.WriteLine(rejectionReason); } else { Trace.WriteLine(" [Pass]"); } } standardPeaks.RemoveAll(scanPredicate); standardPeaks.RemoveAll(massDistanceThreshold); standardPeaks.RemoveAll(shapeThreshold); standardPeaks.RemoveAll(isotopeThreshold); if (standardPeaks.Count == 0) { Trace.WriteLine(string.Format(" [No Match]")); Trace.WriteLine(string.Empty); return new LibraryMatchResult(null, AnalysisStatus.Negative, null); } StandardImsPeak closestPeak = standardPeaks.First(); DriftTimeFeatureDistance shortestDistance = new DriftTimeFeatureDistance(target, standardPeaks.First(), voltageGroup); foreach (var peak in standardPeaks) { DriftTimeFeatureDistance distance = new DriftTimeFeatureDistance(target, peak, voltageGroup); if (distance.CompareTo(shortestDistance) < 0) { closestPeak = peak; } } Trace.WriteLine(string.Format(" [Match]")); Trace.WriteLine(string.Empty); return new LibraryMatchResult(closestPeak, AnalysisStatus.Positive, shortestDistance); } } throw new Exception("No voltage groups in the Dataset match temerature, pressure, or drift tube voltage setting from the library. Matching failed."); }
public void TestScoring() { string formula = "C9H13ClN6"; string fileLocation = Cae; MolecularTarget target = new MolecularTarget(formula, IonizationMethod.Protonated, "CAE"); Console.WriteLine("CompositionWithoutAdduct: " + target.CompositionWithoutAdduct); Console.WriteLine("Monoisotopic ViperCompatibleMass: " + target.MonoisotopicMass); CrossSectionSearchParameters parameters = new CrossSectionSearchParameters(driftTubeLength); var smoother = new SavitzkyGolaySmoother(parameters.NumPointForSmoothing, 2); CrossSectionWorkfow workflow = new CrossSectionWorkfow(fileLocation, "output", parameters); Console.WriteLine("Ionization method: " + target.Adduct); Console.WriteLine("Targeting centerMz: " + target.MassWithAdduct); // Generate Theoretical Isotopic Profile List<Peak> theoreticalIsotopicProfilePeakList = null; if (target.CompositionWithAdduct != null) { string empiricalFormula = target.CompositionWithAdduct.ToPlainString(); var theoreticalFeatureGenerator = new JoshTheorFeatureGenerator(); IsotopicProfile theoreticalIsotopicProfile = theoreticalFeatureGenerator.GenerateTheorProfile(empiricalFormula, 1); theoreticalIsotopicProfilePeakList = theoreticalIsotopicProfile.Peaklist.Cast<Peak>().ToList(); } // Generate VoltageSeparatedAccumulatedXICs var uimfReader = new DataReader(fileLocation); Console.WriteLine("Input file: {0}", fileLocation); VoltageSeparatedAccumulatedXiCs accumulatedXiCs = new VoltageSeparatedAccumulatedXiCs(uimfReader, target.MassWithAdduct, parameters.MzWindowHalfWidthInPpm, driftTubeLength); Console.WriteLine(); // For each voltage, find 2D XIC features foreach (VoltageGroup voltageGroup in accumulatedXiCs.Keys) { Console.WriteLine("Voltage group: {0} V, Frame {1}-{2}, {3:F2}K, {4:F2}Torr", voltageGroup.MeanVoltageInVolts, voltageGroup.FirstFrameNumber, voltageGroup.LastFrameNumber, voltageGroup.MeanTemperatureInKelvin, voltageGroup.MeanPressureInTorr); List<IntensityPoint> intensityPoints = accumulatedXiCs[voltageGroup].IntensityPoints; List<FeatureBlob> featureBlobs = PeakFinding.FindPeakUsingWatershed(intensityPoints, smoother, parameters.FeatureFilterLevel); List<StandardImsPeak> standardPeaks = featureBlobs.Select(featureBlob => new StandardImsPeak(featureBlob, uimfReader, voltageGroup, target.MassWithAdduct, parameters.MzWindowHalfWidthInPpm)).ToList(); // feature scorings and Target selection. double globalMaxIntensity = IMSUtil.MaxIntensityAfterFrameAccumulation(voltageGroup, uimfReader); // Check each XIC Peak found foreach (var featurePeak in standardPeaks) { // Evaluate feature scores. double intensityScore = FeatureScoreUtilities.IntensityScore(featurePeak, globalMaxIntensity); double isotopicScoreAngle = FeatureScoreUtilities.IsotopicProfileScore( featurePeak, workflow.uimfReader, target, theoreticalIsotopicProfilePeakList, voltageGroup, IsotopicScoreMethod.Angle, globalMaxIntensity, workflow.NumberOfScans); double isotopicScoreDistance = FeatureScoreUtilities.IsotopicProfileScore( featurePeak, workflow.uimfReader, target, theoreticalIsotopicProfilePeakList, voltageGroup, IsotopicScoreMethod.EuclideanDistance, globalMaxIntensity, workflow.NumberOfScans); double isotopicScorePerson = FeatureScoreUtilities.IsotopicProfileScore( featurePeak, workflow.uimfReader, target, theoreticalIsotopicProfilePeakList, voltageGroup, IsotopicScoreMethod.PearsonCorrelation, globalMaxIntensity, workflow.NumberOfScans); double isotopicScoreBhattacharyya = FeatureScoreUtilities.IsotopicProfileScore( featurePeak, workflow.uimfReader, target, theoreticalIsotopicProfilePeakList, voltageGroup, IsotopicScoreMethod.Bhattacharyya, globalMaxIntensity, workflow.NumberOfScans); double isotopicScoreDistanceAlternative = FeatureScoreUtilities.IsotopicProfileScore( featurePeak, workflow.uimfReader, target, theoreticalIsotopicProfilePeakList, voltageGroup, IsotopicScoreMethod.EuclideanDistanceAlternative, globalMaxIntensity, workflow.NumberOfScans); double peakShapeScore = FeatureScoreUtilities.PeakShapeScore(featurePeak, workflow.uimfReader, workflow.Parameters.MzWindowHalfWidthInPpm, workflow.Parameters.DriftTimeToleranceInMs, voltageGroup, globalMaxIntensity, workflow.NumberOfScans); // Report all features. Console.WriteLine(" feature found at scan number {0}", featurePeak.PeakApex.DriftTimeCenterInScanNumber); Console.WriteLine(" IntensityScore: {0}", intensityScore); Console.WriteLine(" peakShapeScore: {0}", peakShapeScore); Console.WriteLine(" isotopicScore - Angle: {0}", isotopicScoreAngle); Console.WriteLine(" isotopicScore - Distance: {0}", isotopicScoreDistance); Console.WriteLine(" isotopicScore - Distance2:{0}", isotopicScoreDistanceAlternative); Console.WriteLine(" isotopicScore - Pearson: {0}", isotopicScorePerson); Console.WriteLine(" isotopicScore - Bhattacharyya: {0}", isotopicScoreBhattacharyya); Console.WriteLine(); } Console.WriteLine(); } workflow.Dispose(); }
/// <summary> /// The run molecule informed work flow. /// </summary> /// <param name="target"> /// The Target. /// </param> /// <param name="detailedVerbose"> /// </param> /// <returns> /// The <see cref="CrossSectionWorkflowResult"/>. /// </returns> public CrossSectionWorkflowResult RunCrossSectionWorkFlow(IImsTarget target, bool detailedVerbose = true) { // Reassign trace listener to print to console as well as the target directory. using (this.ResetTraceListenerToTarget(target, this.DatasetName)) { try { // Get the monoisotopic mass for viper, which is different from anything else. double viperFriendlyMass = target.MassWithAdduct; if (target.ChargeState < 0) { viperFriendlyMass = viperFriendlyMass + new Composition(0, target.ChargeState, 0, 0, 0).Mass; } else { viperFriendlyMass = viperFriendlyMass - new Composition(0, Math.Abs(target.ChargeState), 0, 0, 0).Mass; } // Generate Theoretical Isotopic Profile List<Peak> theoreticalIsotopicProfilePeakList = null; if (target.HasCompositionInfo) { int chargeStateAbs = Math.Abs(target.ChargeState); // Again this isotopic profile generator auto adds hydrogen for you depending on charge states. So here take it out. Composition compensatedComposition = target.CompositionWithAdduct - new Composition(0, chargeStateAbs, 0, 0, 0); string empiricalFormula = compensatedComposition.ToPlainString(); IsotopicProfile theoreticalIsotopicProfile = this.theoreticalFeatureGenerator.GenerateTheorProfile(empiricalFormula, chargeStateAbs); theoreticalIsotopicProfilePeakList = theoreticalIsotopicProfile.Peaklist.Cast<Peak>().ToList(); } Trace.WriteLine(string.Format("Dataset: {0}", this.uimfReader.UimfFilePath)); ReportTargetInfo(target, detailedVerbose); double targetMz = Math.Abs(target.MassWithAdduct / target.ChargeState); // Voltage grouping. Note that we only accumulate frames as needed. Accumulate frames globally is too costly. // Here we accumulate the XICs around target MZ. VoltageSeparatedAccumulatedXiCs accumulatedXiCs = new VoltageSeparatedAccumulatedXiCs(this.uimfReader, targetMz, this.Parameters.MzWindowHalfWidthInPpm, this.Parameters.DriftTubeLengthInCm); // Remove voltage groups that don't have sufficient frame accumulations IEnumerable<VoltageGroup> remainingVGs = accumulatedXiCs.Keys; IEnumerable<VoltageGroup> toBeRemoved = VoltageGroupFilters.RemoveVoltageGroupsWithInsufficentFrames(remainingVGs, this.Parameters.InsufficientFramesFraction); foreach (VoltageGroup voltageGroup in toBeRemoved) { accumulatedXiCs.Remove(voltageGroup); } // Perform feature detection and scoring and the given MzInDalton range on the accumulated XICs to get the base peaks. if (detailedVerbose) { Trace.WriteLine("Feature detection and scoring: "); } IList<VoltageGroup> rejectedVoltageGroups = new List<VoltageGroup>(); IList<ObservedPeak> filteredObservations = new List<ObservedPeak>(); IList<ObservedPeak> allObservations = new List<ObservedPeak>(); IDictionary<string, IList<ObservedPeak>> rejectedObservations = new Dictionary<string, IList<ObservedPeak>>(); var numberOfParticipatingVGs = accumulatedXiCs.Keys.Count; // Iterate through the features and perform filtering on isotopic affinity, intensity, drift time and peak shape. foreach (VoltageGroup voltageGroup in accumulatedXiCs.Keys) { double globalMaxIntensity = IMSUtil.MaxIntensityAfterFrameAccumulation(voltageGroup, this.uimfReader); List<StandardImsPeak> standardPeaks = this.FindPeaksBasedOnXIC(voltageGroup, accumulatedXiCs[voltageGroup], target); // Score features IDictionary<StandardImsPeak, PeakScores> scoresTable = new Dictionary<StandardImsPeak, PeakScores>(); if (detailedVerbose) { Trace.WriteLine( string.Format( " Voltage group: {0:F2} V, Frame {1}-{2}, {3:F2}K, {4:F2}Torr", voltageGroup.MeanVoltageInVolts, voltageGroup.FirstFrameNumber, voltageGroup.LastFrameNumber, voltageGroup.MeanTemperatureInKelvin, voltageGroup.MeanPressureInTorr)); } foreach (StandardImsPeak peak in standardPeaks) { PeakScores currentStatistics = FeatureScoreUtilities.ScoreFeature( peak, globalMaxIntensity, this.uimfReader, this.Parameters.MzWindowHalfWidthInPpm, this.Parameters.DriftTimeToleranceInMs, voltageGroup, this.NumberOfScans, target, IsotopicScoreMethod.Angle, theoreticalIsotopicProfilePeakList); scoresTable.Add(peak, currentStatistics); } double maxIntensity = standardPeaks.Max(x => x.SummedIntensities); Predicate<StandardImsPeak> relativeIntensityThreshold = imsPeak => FeatureFilters.FilterOnRelativeIntesity(imsPeak, maxIntensity, this.Parameters.RelativeIntensityPercentageThreshold); // filter out non Target peaks and noise. Predicate<StandardImsPeak> absoluteIntensityThreshold = imsPeak => FeatureFilters.FilterOnAbsoluteIntensity(imsPeak, scoresTable[imsPeak].IntensityScore, this.Parameters.AbsoluteIntensityThreshold); // filter out features with Ims scans at 1% left or right. Predicate<StandardImsPeak> scanPredicate = imsPeak => FeatureFilters.FilterExtremeDriftTime(imsPeak, this.NumberOfScans); // filter out features with bad peak shapes. Predicate<StandardImsPeak> shapeThreshold = imsPeak => FeatureFilters.FilterBadPeakShape(imsPeak, scoresTable[imsPeak].PeakShapeScore, this.Parameters.PeakShapeThreshold); // filter out features with distant isotopic profile. Predicate<StandardImsPeak> isotopeThreshold = imsPeak => FeatureFilters.FilterBadIsotopicProfile(imsPeak, scoresTable[imsPeak].IsotopicScore, this.Parameters.IsotopicThreshold); // Print out candidate features and how they were rejected. foreach (StandardImsPeak peak in standardPeaks) { PeakScores currentStatistics = scoresTable[peak]; string rejectionReason = ReportFeatureEvaluation( peak, currentStatistics, detailedVerbose, target, scanPredicate(peak), absoluteIntensityThreshold(peak), relativeIntensityThreshold(peak), shapeThreshold(peak), isotopeThreshold(peak)); bool pass = string.IsNullOrEmpty(rejectionReason); ObservedPeak analyzedPeak = new ObservedPeak(voltageGroup, peak, currentStatistics); if (pass) { filteredObservations.Add(analyzedPeak); } else { if (rejectedObservations.ContainsKey(rejectionReason)) { rejectedObservations[rejectionReason].Add(analyzedPeak); } else { rejectedObservations.Add(rejectionReason, new List<ObservedPeak>(){analyzedPeak}); } } allObservations.Add(analyzedPeak); } standardPeaks.RemoveAll(scanPredicate); standardPeaks.RemoveAll(absoluteIntensityThreshold); standardPeaks.RemoveAll(relativeIntensityThreshold); standardPeaks.RemoveAll(shapeThreshold); if (target.HasCompositionInfo) { standardPeaks.RemoveAll(isotopeThreshold); } if (standardPeaks.Count == 0) { if (detailedVerbose) { Trace.WriteLine(string.Format(" (All features were rejected in voltage group {0:F4} V)", voltageGroup.MeanVoltageInVolts)); Trace.WriteLine(string.Empty); Trace.WriteLine(string.Empty); } rejectedVoltageGroups.Add(voltageGroup); } // Rate the feature's VoltageGroupScoring score. VoltageGroupScoring score measures how likely the voltage group contains and detected the Target ion. voltageGroup.VoltageGroupScore = VoltageGroupScoring.ComputeVoltageGroupStabilityScore(voltageGroup); } // Remove voltage groups that were rejected foreach (VoltageGroup voltageGroup in rejectedVoltageGroups) { accumulatedXiCs.Remove(voltageGroup); } IEnumerable<ObservedPeak> rejectedPeaks = rejectedObservations.Values.SelectMany(x => x); // Report analysis as negative if (accumulatedXiCs.Keys.Count == 0) { CrossSectionWorkflowResult informedResult = CrossSectionWorkflowResult.CreateNegativeResult(rejectedPeaks, rejectedVoltageGroups, target, this.DatasetPath, this.OutputPath, this.SampleCollectionDate); ReportAnslysisResultAndMetrics(informedResult, detailedVerbose); return informedResult; } else { // Perform the data association algorithm. IIonTracker tracker = new CombinatorialIonTracker(3000); // Because for somereason we are not keeping track of drift tube length in UIMF...so we kind of have to go ask the instrument operator.. double driftTubeLength = this.Parameters.DriftTubeLengthInCm; AssociationHypothesis optimalAssociationHypothesis = tracker.FindOptimumHypothesis(filteredObservations, driftTubeLength, target, this.Parameters, numberOfParticipatingVGs); if (optimalAssociationHypothesis == null) { CrossSectionWorkflowResult negResult = CrossSectionWorkflowResult.CreateNegativeResult(rejectedPeaks, rejectedVoltageGroups, target, this.DatasetPath, this.OutputPath, this.SampleCollectionDate); ReportAnslysisResultAndMetrics(negResult, detailedVerbose); return negResult; } if (detailedVerbose) { Console.WriteLine("Writes QC plot of fitline to " + this.OutputPath); Trace.WriteLine(string.Empty); } string extension = (this.Parameters.GraphicsExtension.StartsWith(".")) ? this.Parameters.GraphicsExtension : "." + this.Parameters.GraphicsExtension; string outputPath = string.Format("{0}target_{1}_in_{2}_QA{3}", this.OutputPath, target.TargetDescriptor, this.DatasetName, extension); ImsInformedPlotter plotter = new ImsInformedPlotter(); plotter.PlotAssociationHypothesis(optimalAssociationHypothesis, outputPath, this.DatasetName, target, rejectedObservations); // Printout results if (detailedVerbose) { Trace.WriteLine("Target Data Association"); int count = 0; foreach (IsomerTrack track in optimalAssociationHypothesis.Tracks) { Trace.WriteLine(string.Format(" T{0}: ", count)); foreach (ObservedPeak peak in track.ObservedPeaks) { Trace.WriteLine(string.Format(" [td: {0:F4}ms, V: {1:F4}V, T: {2:F4}K, P: {3:F4}Torr]", peak.Peak.PeakApex.DriftTimeCenterInMs, peak.VoltageGroup.MeanVoltageInVolts, peak.VoltageGroup.MeanTemperatureInKelvin, peak.VoltageGroup.MeanPressureInTorr)); } count++; Trace.WriteLine(""); } Trace.WriteLine(""); } // Remove outliers with high influence. // FitLine.RemoveOutliersAboveThreshold(3, minFitPoints); // Remove outliers until min fit point is reached or good R2 is achieved. // while (TrackFilter.IsLowR2(FitLine.RSquared) && FitLine.FitPointCollection.Count > minFitPoints) // { // FitLine.RemoveOutlierWithHighestCookDistance(minFitPoints); // } // Remove the voltage considered outliers // foreach (VoltageGroup voltageGroup in accumulatedXiCs.Keys.Where(p => FitLine.OutlierCollection.Contains(p.FitPoint)).ToList()) // { // accumulatedXiCs.Remove(voltageGroup); // } CrossSectionWorkflowResult informedResult = CrossSectionWorkflowResult.CreateResultFromAssociationHypothesis( this.Parameters, optimalAssociationHypothesis, target, accumulatedXiCs.Keys, allObservations, this.DatasetPath, this.OutputPath, this.SampleCollectionDate, viperFriendlyMass ); ReportAnslysisResultAndMetrics(informedResult, detailedVerbose); Trace.Listeners.Clear(); return informedResult; } } catch (Exception e) { // Print result Trace.WriteLine(e.Message); Trace.WriteLine(e.StackTrace); Trace.Listeners.Clear(); Trace.Close(); Trace.Listeners.Clear(); // create the error result return CrossSectionWorkflowResult.CreateErrorResult(target, this.DatasetName, this.DatasetPath, this.OutputPath, this.SampleCollectionDate); } } }
public void TestFormulaPerturbance() { List<Tuple<string, string>> formulas = new List<Tuple<string, string>>(); // truth formulas.Add(new Tuple<string, string>("True formula", "C12H10O4S")); formulas.Add(new Tuple<string, string>("1 extra H", "C12H11O4S")); formulas.Add(new Tuple<string, string>("2 extra H", "C12H12O4S")); formulas.Add(new Tuple<string, string>("3 extra H", "C12H13O4S")); formulas.Add(new Tuple<string, string>("3 extra H", "C12H14O4S")); formulas.Add(new Tuple<string, string>("4 extra H", "C12H15O4S")); formulas.Add(new Tuple<string, string>("5 extra H", "C12H16O4S")); formulas.Add(new Tuple<string, string>("1 less H", "C12H9O4S")); formulas.Add(new Tuple<string, string>("2 less H", "C12H8O4S")); formulas.Add(new Tuple<string, string>("3 less H", "C12H7O4S")); formulas.Add(new Tuple<string, string>("4 less H", "C12H6O4S")); Console.WriteLine("[Intensity], [Distance1], [Distance2], [Angle], [Pearson], [Bucha]"); string fileLocation = BPSNegative; CrossSectionSearchParameters parameters = new CrossSectionSearchParameters(driftTubeLength); CrossSectionWorkfow workflow = new CrossSectionWorkfow(fileLocation, "output", parameters); foreach (var form in formulas) { bool found = false; MolecularTarget target = new MolecularTarget(form.Item2, new IonizationAdduct(IonizationMethod.Deprotonated), form.Item1); Console.Write(form.Item1 + ": "); var smoother = new SavitzkyGolaySmoother(parameters.NumPointForSmoothing, 2); // Generate Theoretical Isotopic Profile List<Peak> theoreticalIsotopicProfilePeakList = null; if (target.CompositionWithAdduct != null) { string empiricalFormula = target.CompositionWithAdduct.ToPlainString(); var theoreticalFeatureGenerator = new JoshTheorFeatureGenerator(); IsotopicProfile theoreticalIsotopicProfile = theoreticalFeatureGenerator.GenerateTheorProfile(empiricalFormula, 1); theoreticalIsotopicProfilePeakList = theoreticalIsotopicProfile.Peaklist.Cast<Peak>().ToList(); } // Generate VoltageSeparatedAccumulatedXICs var uimfReader = new DataReader(fileLocation); VoltageSeparatedAccumulatedXiCs accumulatedXiCs = new VoltageSeparatedAccumulatedXiCs(uimfReader, target.MassWithAdduct, parameters.MzWindowHalfWidthInPpm, parameters.DriftTubeLengthInCm); var voltageGroup = accumulatedXiCs.Keys.First(); // Find peaks using multidimensional peak finder. List<IntensityPoint> intensityPoints = accumulatedXiCs[voltageGroup].IntensityPoints; List<FeatureBlob> featureBlobs = PeakFinding.FindPeakUsingWatershed(intensityPoints, smoother, parameters.FeatureFilterLevel); List<StandardImsPeak> standardPeaks = featureBlobs.Select(featureBlob => new StandardImsPeak(featureBlob, uimfReader, voltageGroup, target.MassWithAdduct, parameters.MzWindowHalfWidthInPpm)).ToList(); // feature scorings and Target selection. double globalMaxIntensity = IMSUtil.MaxIntensityAfterFrameAccumulation(voltageGroup, uimfReader); // Check each XIC Peak found foreach (var peak in standardPeaks) { // Evaluate feature scores. double intensityScore = FeatureScoreUtilities.IntensityScore(peak, globalMaxIntensity); double isotopicScoreAngle = FeatureScoreUtilities.IsotopicProfileScore( peak, workflow.uimfReader, target, theoreticalIsotopicProfilePeakList, voltageGroup, IsotopicScoreMethod.Angle, globalMaxIntensity, workflow.NumberOfScans); double isotopicScoreDistance = FeatureScoreUtilities.IsotopicProfileScore( peak, workflow.uimfReader, target, theoreticalIsotopicProfilePeakList, voltageGroup, IsotopicScoreMethod.EuclideanDistance, globalMaxIntensity, workflow.NumberOfScans); double isotopicScorePerson = FeatureScoreUtilities.IsotopicProfileScore( peak, workflow.uimfReader, target, theoreticalIsotopicProfilePeakList, voltageGroup, IsotopicScoreMethod.PearsonCorrelation, globalMaxIntensity, workflow.NumberOfScans); double isotopicScoreBhattacharyya = FeatureScoreUtilities.IsotopicProfileScore( peak, workflow.uimfReader, target, theoreticalIsotopicProfilePeakList, voltageGroup, IsotopicScoreMethod.Bhattacharyya, globalMaxIntensity, workflow.NumberOfScans); double isotopicScoreDistanceAlternative = FeatureScoreUtilities.IsotopicProfileScore( peak, workflow.uimfReader, target, theoreticalIsotopicProfilePeakList, voltageGroup, IsotopicScoreMethod.EuclideanDistanceAlternative, globalMaxIntensity, workflow.NumberOfScans); double peakShapeScore = FeatureScoreUtilities.PeakShapeScore(peak, workflow.uimfReader, workflow.Parameters.MzWindowHalfWidthInPpm, workflow.Parameters.DriftTimeToleranceInMs, voltageGroup, globalMaxIntensity, workflow.NumberOfScans); // Report all features. if (peak.PeakApex.DriftTimeCenterInScanNumber == 115) { Console.Write("{0:F4} ", intensityScore); found = true; } // Report all features. if (peak.PeakApex.DriftTimeCenterInScanNumber == 115) { Console.Write("{0:F4} ", isotopicScoreDistance); found = true; } // Report all features. if (peak.PeakApex.DriftTimeCenterInScanNumber == 115) { Console.Write("{0:F4} ", isotopicScoreDistanceAlternative); found = true; } // Report all features. if (peak.PeakApex.DriftTimeCenterInScanNumber == 115) { Console.Write("{0:F4} ", isotopicScoreAngle); found = true; } // Report all features. if (peak.PeakApex.DriftTimeCenterInScanNumber == 115) { Console.Write("{0:F4} ", isotopicScorePerson); found = true; } // Report all features. if (peak.PeakApex.DriftTimeCenterInScanNumber == 115) { Console.Write("{0:F4} ", isotopicScoreBhattacharyya); found = true; } } if (!found) { Console.Write("No features"); } Console.WriteLine(); } // Manually dispose so it doesn't interfere with other tests. workflow.Dispose(); }