/// <summary> /// Aligns features to the baseline correcting for drift time. /// </summary> /// <param name="fullObservedEnumerable">All features.</param> /// <param name="observedEnumerable">Filtered features to use for drift time correction.</param> /// <param name="targetEnumerable">Expected features that should be filtered.</param> /// <param name="massTolerance">PPM Mass Tolerance.</param> /// <param name="netTolerance">Normalized Elution Time Tolerance.</param> public static DriftTimeAlignmentResults <TTarget, TObserved> AlignObservedEnumerable(IEnumerable <UMCLight> fullObservedEnumerable, IEnumerable <TTarget> observedEnumerable, IEnumerable <TObserved> targetEnumerable, double massTolerance, double netTolerance) { // Setup Tolerance for Feature Matching var featureMatcherParameters = new FeatureMatcherParameters(); featureMatcherParameters.SetTolerances(massTolerance, netTolerance, DRIFT_TIME_TOLERANCE); featureMatcherParameters.UseDriftTime = true; // Find all matches based on defined tolerances var featureMatcher = new FeatureMatcher.FeatureMatcher <TTarget, TObserved>(observedEnumerable.ToList(), targetEnumerable.ToList(), featureMatcherParameters); var matchList = featureMatcher.FindMatches(observedEnumerable.ToList(), targetEnumerable.ToList(), featureMatcherParameters.UserTolerances, 0); // Create <ObservedDriftTime, TargetDriftTime> XYData List var xyDataList = new List <XYData>(); foreach (var featureMatch in matchList) { var xyData = new XYData(featureMatch.ObservedFeature.DriftTime, featureMatch.TargetFeature.DriftTime); xyDataList.Add(xyData); } var linearRegression = new LinearRegressionModel(); // Find the Linear Equation for the <ObservedDriftTime, TargetDriftTime> XYData List var linearEquation = linearRegression.CalculateRegression(xyDataList); // Set the Aligned Drift Time value for each of the observed Features, even if they were not found in matching foreach (var observedT in fullObservedEnumerable) { observedT.DriftTimeAligned = linearRegression.Transform(linearEquation, observedT.DriftTime); } var results = new DriftTimeAlignmentResults <TTarget, TObserved>(matchList, linearEquation); return(results); }
AlignDriftTimes(List <UMCLight> features, List <UMCLight> baselineFeatures, DriftTimeAlignmentOptions options) { UpdateStatus("Correcting drift times."); var baselineUmCs = new List <UMCLight>(); var aligneeUmCs = new List <UMCLight>(); UpdateStatus("Mapping data structures."); var featureIdMap = new Dictionary <int, UMCLight>(); foreach (var feature in features) { var umc = new UMCLight { MassMonoisotopicAligned = feature.MassMonoisotopicAligned, NetAligned = feature.NetAligned, DriftTime = Convert.ToSingle(feature.DriftTime), Id = feature.Id, ChargeState = feature.ChargeState }; aligneeUmCs.Add(umc); featureIdMap.Add(feature.Id, feature); } foreach (var feature in baselineFeatures) { var umc = new UMCLight { MassMonoisotopicAligned = feature.MassMonoisotopicAligned, NetAligned = feature.Net, DriftTime = Convert.ToSingle(feature.DriftTime), Id = feature.Id, ChargeState = feature.ChargeState }; baselineUmCs.Add(umc); } // filter based on charge state. var chargeMax = options.MaxChargeState; var chargeMin = options.MinChargeState; UpdateStatus(string.Format("Filtering Features Min Charge: {0} <= charge <= Max Charge {1}", chargeMin, chargeMax)); var filteredQuery = from feature in aligneeUmCs where feature.ChargeState <= chargeMax && feature.ChargeState >= chargeMin select feature; var filteredUmCs = filteredQuery.ToList(); UpdateStatus("Finding Aligned Matches and correcting drift times."); var alignedResults = DriftTimeAlignment <UMCLight, UMCLight> .AlignObservedEnumerable(aligneeUmCs, filteredUmCs, baselineUmCs, options.MassPPMTolerance, options.NETTolerance); DriftTimeAlignmentResults <UMCLight, UMCLight> offsetResults = null; if (options.ShouldPerformOffset) { UpdateStatus("Adjusting drift time offsets."); var aligneeData = aligneeUmCs; if (!options.ShouldUseAllObservationsForOffsetCalculation) { UpdateStatus("Using only filtered matches for offset correction."); aligneeData = filteredUmCs; } else { UpdateStatus("Using all feature matches for offset correction."); } offsetResults = DriftTimeAlignment <UMCLight, UMCLight> .CorrectForOffset(aligneeData, baselineUmCs, options.MassPPMTolerance, options.NETTolerance, options.DriftTimeTolerance); } UpdateStatus("Remapping data structures for persistence to database."); foreach (var umc in aligneeUmCs) { featureIdMap[umc.Id].DriftTime = umc.DriftTimeAligned; } var pair = new KeyValuePair <DriftTimeAlignmentResults <UMCLight, UMCLight>, DriftTimeAlignmentResults <UMCLight, UMCLight> >( alignedResults, offsetResults); return(pair); }
/// <summary> /// Does a zero mean drift time correction. /// </summary> /// <param name="observedEnumerable">All observed features to shift that should already be drift time aligned.</param> /// <param name="targetEnumerable">Expected features</param> /// <param name="massTolerance">PPM Mass Tolerance</param> /// <param name="netTolerance">Normalized Elution Time tolerance.</param> /// <param name="driftTimeTolerance">Drift time tolerance to use.</param> public static DriftTimeAlignmentResults <TTarget, TObserved> CorrectForOffset(IEnumerable <TTarget> observedEnumerable, IEnumerable <TObserved> targetEnumerable, double massTolerance, double netTolerance, double driftTimeTolerance) { // Setup Tolerance for Feature Matching var featureMatcherParameters = new FeatureMatcherParameters(); featureMatcherParameters.SetTolerances(massTolerance, netTolerance, (float)driftTimeTolerance); featureMatcherParameters.UseDriftTime = true; // Find all matches based on defined tolerances var featureMatcher = new FeatureMatcher.FeatureMatcher <TTarget, TObserved>(observedEnumerable.ToList(), targetEnumerable.ToList(), featureMatcherParameters); var matchList = featureMatcher.FindMatches(observedEnumerable.ToList(), targetEnumerable.ToList(), featureMatcherParameters.UserTolerances, 0); // Create List of Drift Time differences var differenceList = new List <double>(matchList.Count); foreach (var featureMatch in matchList) { var observedFeature = featureMatch.ObservedFeature; var targetFeature = featureMatch.TargetFeature; double observedDriftTime; if (observedFeature.DriftTimeAligned != double.NaN && observedFeature.DriftTimeAligned > 0.0) { observedDriftTime = observedFeature.DriftTimeAligned; } else { observedDriftTime = observedFeature.DriftTime; } double targetDriftTime; if (!double.IsNaN(targetFeature.DriftTimeAligned) && targetFeature.DriftTimeAligned > 0.0) { targetDriftTime = targetFeature.DriftTimeAligned; } else { targetDriftTime = targetFeature.DriftTime; } differenceList.Add(observedDriftTime - targetDriftTime); } // Create bins for histogram var bins = new List <double>(); for (var i = -driftTimeTolerance; i <= driftTimeTolerance; i += (driftTimeTolerance / 100.0)) { bins.Add(i); } bins.Add(driftTimeTolerance); // Group drift time differences into the bins var groupings = differenceList.GroupBy(difference => bins.First(bin => bin >= difference)); // Order the groupings by their count, so the group with the highest count will be first var orderGroupingsByCount = from singleGroup in groupings orderby singleGroup.Count() descending select singleGroup; // Grab the drift time from the group with the most counts var driftTimeOffset = orderGroupingsByCount.First().Key; // Update all of the observed features with the new drift time foreach (var observedFeature in observedEnumerable) { if (!double.IsNaN(observedFeature.DriftTimeAligned) && observedFeature.DriftTimeAligned > 0.0) { observedFeature.DriftTimeAligned -= driftTimeOffset; } else { observedFeature.DriftTime -= (float)driftTimeOffset; } } var linearEquation = new LinearRegressionResult { Slope = 0, Intercept = driftTimeOffset }; var results = new DriftTimeAlignmentResults <TTarget, TObserved>(matchList, linearEquation); return(results); }