public void PlotAssociationHypothesis(AssociationHypothesis hypothesis, string plotLocation, string datasetName, IImsTarget target, IDictionary<string, IList<ObservedPeak>> preFilteredPeaks) { //int width = 450; //int height = 256; int width = 675; int height = 384; PlotModel associationHypothsisPlot = this.AssociationHypothesisPlot(hypothesis, datasetName, target); associationHypothsisPlot = this.AnnotateRemovedPeaks(associationHypothsisPlot, preFilteredPeaks); this.PlotDiagram(plotLocation, associationHypothsisPlot, width, height); }
/// <summary> /// The find all hypothesis. /// </summary> /// <param name="validTracks"> /// The valid tracks. /// </param> /// <param name="allPeaks"></param> /// <returns> /// The <see cref="IEnumerable"/>. /// </returns> private IEnumerable<AssociationHypothesis> FindAllHypothesis(IEnumerable<IsomerTrack> validTracks, IEnumerable<ObservedPeak> allPeaks) { allPeaks = allPeaks.ToArray(); List<IsomerTrack> tracks = validTracks.ToList(); const int AlgorithmLimit = 20; int size = tracks.Count; if (size >= AlgorithmLimit) { tracks = tracks.GetRange(0, AlgorithmLimit); size = tracks.Count; } int totalCombinations = (int)Math.Pow(2, size) - 1; AssociationHypothesis association = new AssociationHypothesis(allPeaks); bool hasConflicted = false; for (int i = 0; i < totalCombinations - 1; i++) { long grey = Combinatorics.BinaryToGray(i + 1); if (hasConflicted) { association = new AssociationHypothesis(allPeaks); hasConflicted = false; int[] indexOfOnes = Combinatorics.GreyCodeToIndexOfOnes(grey).ToArray(); foreach (var index in indexOfOnes) { hasConflicted = association.IsConflict(tracks[index]); if (!hasConflicted) { association.AddIsomerTrack(tracks[index]); } else { break; } } if (!hasConflicted) { yield return (AssociationHypothesis)association.Clone(); } } else { bool addOrNotRemove; var index = Combinatorics.NextChangeOnGrey(i, out addOrNotRemove); if (addOrNotRemove) { IsomerTrack candiateTrack = tracks[index]; if (association.IsConflict(candiateTrack)) { hasConflicted = true; } else { association.AddIsomerTrack(tracks[index]); yield return (AssociationHypothesis)association.Clone(); } } else { association.RemoveIsomerTrack(tracks[index]); yield return (AssociationHypothesis)association.Clone(); } } } }
internal static CrossSectionWorkflowResult CreateResultFromAssociationHypothesis(CrossSectionSearchParameters parameters, AssociationHypothesis optimalHypothesis, IImsTarget target, IEnumerable<VoltageGroup> allVoltageGroups, IEnumerable<ObservedPeak> allPeaks, string datasetPath, string analysisPath, string sampleCollectionDate, double viperCompatibleMass = 0) { // Initialize the result struct. AssociationHypothesisInfo associationHypothesisInfo = new AssociationHypothesisInfo(optimalHypothesis.ProbabilityOfDataGivenHypothesis, optimalHypothesis.ProbabilityOfHypothesisGivenData); double averageVoltageGroupScore = VoltageGroupScoring.ComputeAverageVoltageGroupStabilityScore(allVoltageGroups); IEnumerable<PeakScores> allFeatureStatistics = allPeaks.Select(x => x.Statistics); PeakScores averageObservedPeakStatistics = FeatureScoreUtilities.AverageFeatureStatistics(allFeatureStatistics); IEnumerable<IsomerTrack> tracks = optimalHypothesis.Tracks.ToList(); // Find the conformer with the closest m/z IsomerTrack trackWithBestMz = tracks.OrderBy(x => Math.Abs(Metrics.DaltonToPpm(x.AverageMzInDalton - target.MassWithAdduct, target.MassWithAdduct))).First(); double bestMzInPpm = Metrics.DaltonToPpm(trackWithBestMz.AverageMzInDalton - target.MassWithAdduct, target.MassWithAdduct); IList<IdentifiedIsomerInfo> isomersInfo = tracks.Select(x => x.ExportIdentifiedIsomerInfo(viperCompatibleMass, allVoltageGroups.Count() - parameters.MaxOutliers, parameters.MinR2, target, bestMzInPpm)).ToList(); AnalysisStatus finalStatus = TrackToHypothesisConclusionLogic(isomersInfo.Select(info => info.AnalysisStatus)); CrossSectionWorkflowResult informedResult = new CrossSectionWorkflowResult( datasetPath, target, finalStatus, associationHypothesisInfo, isomersInfo, averageObservedPeakStatistics, averageVoltageGroupScore, analysisPath, sampleCollectionDate ); return informedResult; }
/// <summary> /// The association hypothesis plot. /// </summary> /// <param name="hypothesis"> /// The hypothesis. /// </param> /// <param name="datasetName"> /// The dataset name. /// </param> /// <param name="targetDescriptor"> /// The target descriptor. /// </param> /// <returns> /// The <see cref="PlotModel"/>. /// </returns> private PlotModel AssociationHypothesisPlot(AssociationHypothesis hypothesis, string datasetName, IImsTarget target, bool plotXAxisFromZero = false) { PlotModel model = new PlotModel(); model.LegendBorderThickness = 0; model.LegendOrientation = LegendOrientation.Vertical; model.LegendPlacement = LegendPlacement.Inside; model.LegendPosition = LegendPosition.LeftTop; model.TitlePadding = 0; model.Title = "Optimal Association Hypothesis Plot"; model.Subtitle = string.Format("Target: {0}, dataset: {1}", target.TargetDescriptor, datasetName) ; model.Axes.Add( new LinearAxis { Title = "IMS arrival time (milliseconds)", MajorGridlineStyle = LineStyle.Solid, Position = AxisPosition.Left, }); model.Axes.Add( new LinearAxis { Title = "P/(T*V) with P and T nondimensionalized (1/V)", Position = AxisPosition.Bottom, MajorGridlineStyle = LineStyle.Solid, }); // Add all the points IEnumerable<ObservedPeak> onTrackPeaks = hypothesis.OnTrackObservations; IEnumerable<ObservedPeak> offTrackPeaks = hypothesis.AllObservations.Where(x => !hypothesis.IsOnTrack(x)); Func<ObservedPeak, ScatterPoint> fitPointMap = obj => { ObservedPeak observation = obj; ContinuousXYPoint xyPoint = observation.ToContinuousXyPoint(false, 0); double size = MapToPointSize(observation); ScatterPoint sp = new ScatterPoint(xyPoint.X, xyPoint.Y, size); return sp; }; var ontrackSeries= new ScatterSeries { Title = "[Peaks On Tracks]", MarkerFill = OxyColors.BlueViolet, MarkerType = MarkerType.Circle }; var offtrackSeries= new ScatterSeries { Title = "[Peaks Off Tracks]", MarkerFill = OxyColors.Red, MarkerType = MarkerType.Circle }; ontrackSeries.Points.AddRange(onTrackPeaks.Select(x => fitPointMap(x))); offtrackSeries.Points.AddRange(offTrackPeaks.Select(x => fitPointMap(x))); model.Series.Add(ontrackSeries); model.Series.Add(offtrackSeries); var allTracks = hypothesis.Tracks; // Add the tracks as linear axes int count = 1; foreach (var track in allTracks) { FitLine fitline = track.FitLine; LineAnnotation annotation = new LineAnnotation(); annotation.Slope = fitline.Slope; annotation.Intercept = fitline.Intercept; annotation.TextPadding = 3; annotation.TextMargin = 2; annotation.Text = string.Format("Conformer {0} - mz: {1:F2}; ccs: {2:F2}, Isotopic Score: {3:F3}; Track Probability: {4:F2}; R2: {5:F5};", count, track.AverageMzInDalton, track.GetMobilityInfoForTarget(target).CollisionCrossSectionArea, track.TrackStatistics.IsotopicScore, track.TrackProbability, track.FitLine.RSquared); count++; model.Annotations.Add(annotation); //Func<object, DataPoint> lineMap = obj => //{ // ObservedPeak observation = (ObservedPeak)obj; // ContinuousXYPoint xyPoint = observation.ToContinuousXyPoint(); // double x = xyPoint.X; // double y = fitline.ModelPredictX2Y(x); // DataPoint sp = new DataPoint(x, y); // return sp; //}; //model.Series.Add(new LineSeries() //{ // Mapping = lineMap, // ItemsSource = track.ObservedPeaks, // Color = OxyColors.Purple //}); } return model; }
/// <summary> /// The report track information. /// </summary> /// <param name="hypothesis"> /// The hypothesis. /// </param> /// <param name="hasCompositionInfo"> /// The has Composition Info. /// </param> /// <param name="verbose"> /// The verbose. /// </param> private static void ReportTrackInformation(AssociationHypothesis hypothesis, bool hasCompositionInfo, bool verbose) { foreach (IsomerTrack track in hypothesis.Tracks) { foreach (var observation in track.ObservedPeaks) { VoltageGroup voltageGroup = observation.VoltageGroup; StandardImsPeak peak = observation.Peak; double driftTimeInMs = peak.PeakApex.DriftTimeCenterInMs; // Normalize the drift time to be displayed. double normalizedDriftTimeInMs = IMSUtil.NormalizeDriftTime(driftTimeInMs, voltageGroup); if (verbose) { Trace.WriteLine( string.Format( " Target presence confirmed at {0:F2} ± {1:F2} V.", voltageGroup.MeanVoltageInVolts, Math.Sqrt(voltageGroup.VarianceVoltage))); Trace.WriteLine( string.Format( " Frame range: [{0}, {1}]", voltageGroup.FirstFrameNumber, voltageGroup.LastFrameNumber)); Trace.WriteLine( string.Format( " Normalized Drift Time: {0:F4} ms (Scan# = {1})", normalizedDriftTimeInMs, peak.PeakApex.DriftTimeCenterInScanNumber)); Trace.WriteLine(string.Format(" VoltageGroupScoring: {0:F4}", voltageGroup.VoltageGroupScore)); Trace.WriteLine(string.Format(" IntensityScore: {0:F4}", observation.Statistics.IntensityScore)); if (hasCompositionInfo) { Trace.WriteLine(string.Format(" IsotopicScore: {0:F4}", observation.Statistics.IsotopicScore)); } Trace.WriteLine(string.Format(" PeakShapeScore: {0:F4}", observation.Statistics.PeakShapeScore)); Trace.WriteLine(string.Empty); } } } }