public static FeatureMatch CreateFeatureMatch(this DbFeature feature, string searchTerm) { var match = new FeatureMatch() { FeatureName = feature.Title, ShortenedDescription = feature.Description?.Substring(0, Math.Min(feature.Description.Length, 100)) + "...", ProductName = feature.Product, GroupName = feature.Group, Version = feature.Versions.OrderBy(v => v, new SemanticVersionComparer()).FirstOrDefault(), Tags = feature.Tags.ToList() }; string[] searchTerms = searchTerm.Split(" ", StringSplitOptions.RemoveEmptyEntries); string matchingText = FindMatchingText(feature.Description, searchTerms); if (String.IsNullOrEmpty(matchingText) && feature.Background != null) { matchingText = FindMatchingText(feature.Background.ToString(), searchTerms); } var enumerator = feature.Scenarios.GetEnumerator(); while (String.IsNullOrEmpty(matchingText) && enumerator.MoveNext()) { matchingText = FindMatchingText(enumerator.Current.ToString(), searchTerms); } match.MatchingText = matchingText; return(match); }
public void FindMatchTest() { long matchTime; using (Mat modelImage = CvInvoke.Imread(@"C:\\imgs\Model.jpeg", ImreadModes.Color)) using (Mat observedImage = CvInvoke.Imread(@"C:\\imgs\Test.jpg", ImreadModes.Color)) { Mat result = FeatureMatch.Draw(modelImage, observedImage, out matchTime); } }
/// <summary> /// Matches a list of features to a list of mass tags. /// </summary> /// <param name="features"></param> /// <param name="tags"></param> /// <returns></returns> public List <FeatureMatch <T, U> > MatchFeatures(List <T> features, List <U> tags, PeakMatcherOptions options) { var matches = new List <FeatureMatch <T, U> >(); // Construct a large array of features so we can do searching in linear time. var allFeatures = new List <FeatureLight>(); foreach (var copyFeature in features) { allFeatures.Add(copyFeature); } foreach (var copyTag in tags) { allFeatures.Add(copyTag); } // Sort by mass, gives us the best search time. allFeatures.Sort(FeatureLight.MassComparison); var netTolerance = options.Tolerances.Net; var massTolerance = options.Tolerances.Mass; var driftTolerance = options.Tolerances.DriftTime; var shift = options.DaltonShift; var N = allFeatures.Count; var elementNumber = 0; // This was a linear search, now O(N^2). Need to improve. while (elementNumber < N) { var feature = allFeatures[elementNumber]; var massTag = feature as U; if (massTag == null) { var lowerNET = feature.Net - netTolerance; var higherNET = feature.Net + netTolerance; var lowerDritfTime = feature.DriftTime - driftTolerance; var higherDriftTime = feature.DriftTime + driftTolerance; var currentMassTolerance = feature.MassMonoisotopicAligned * massTolerance / 1000000.0; var lowerMass = feature.MassMonoisotopicAligned - currentMassTolerance; var higherMass = feature.MassMonoisotopicAligned + currentMassTolerance; var matchIndex = elementNumber - 1; while (matchIndex >= 0) { var toMatchFeature = allFeatures[matchIndex]; if (toMatchFeature.MassMonoisotopicAligned < lowerMass) { break; } var tag = toMatchFeature as U; if (tag != null) { if (lowerNET <= tag.Net && tag.Net <= higherNET) { if (lowerDritfTime <= tag.DriftTime && tag.DriftTime <= higherDriftTime) { var match = new FeatureMatch <T, U>(feature as T, tag, false, false); matches.Add(match); } } } matchIndex--; } matchIndex = elementNumber + 1; while (matchIndex < N) { var toMatchFeature = allFeatures[matchIndex]; if (toMatchFeature.MassMonoisotopicAligned > higherMass) { break; } var tag = toMatchFeature as U; if (tag != null) { if (lowerNET <= tag.Net && tag.Net <= higherNET) { if (lowerDritfTime <= tag.DriftTime && tag.DriftTime <= higherDriftTime) { var match = new FeatureMatch <T, U>(feature as T, tag, false, false); matches.Add(match); } } } matchIndex++; } } elementNumber++; } return(matches); }
/// <summary> /// Find a list of matches between two lists. /// </summary> /// <param name="shortObservedList">List of observed features. Possibly a subset of the entire list corresponding to a particular charge state.</param> /// <param name="shortTargetList">List of target features. Possibly a subset of the entire list corresponding to a particular charge state.</param> /// <param name="tolerances">Tolerances to be used for matching.</param> /// <param name="shiftAmount">A fixed shift amount to use for populating the shifted match list.</param> /// <returns>A list of type FeatureMatch containing matches within the defined region.</returns> public List <FeatureMatch <TObserved, TTarget> > FindMatches(List <TObserved> shortObservedList, List <TTarget> shortTargetList, FeatureMatcherTolerances tolerances, double shiftAmount) { // Create a list to hold the matches until they are returned. var matchList = new List <FeatureMatch <TObserved, TTarget> >(); // Set indices to use when iterating over the lists. var observedIndex = 0; var lowerBound = 0; // Sort both lists by mass. if (!double.IsNaN(shortObservedList[0].MassMonoisotopicAligned) && shortObservedList[0].MassMonoisotopicAligned > 0.0) { shortObservedList.Sort(FeatureLight.MassAlignedComparison); } else { shortObservedList.Sort(FeatureLight.MassComparison); } if (!double.IsNaN(shortTargetList[0].MassMonoisotopicAligned) && shortTargetList[0].MassMonoisotopicAligned > 0.0) { shortTargetList.Sort(FeatureLight.MassAlignedComparison); } else { shortTargetList.Sort(FeatureLight.MassComparison); } // Locally store the tolerances. var massTolerancePpm = tolerances.MassTolerancePPM; var netTolerance = tolerances.NETTolerance; var driftTimeTolerance = tolerances.DriftTimeTolerance; // Iterate through the list of observed features. while (observedIndex < shortObservedList.Count) { // Store the current observed feature locally. var observedFeature = shortObservedList[observedIndex]; // Flag variable that gets set to false when the observed mass is greater than the current mass tag by more than the tolerance. var continueLoop = true; // Set the target feature iterator to the current lower bound. var targetIndex = lowerBound; // Iterate through the list of target featrues or until the observed feature is too great. while (targetIndex < shortTargetList.Count && continueLoop) { // Add any shift to the mass tag. var targetFeature = shortTargetList[targetIndex]; // Check to see that the features are within the mass tolearance of one another. double massDifference; if (WithinMassTolerance(observedFeature, targetFeature, massTolerancePpm, shiftAmount, out massDifference)) { var withinTolerances = WithinNETTolerance(observedFeature, targetFeature, netTolerance); if (m_matchParameters.UseDriftTime) { withinTolerances = withinTolerances & WithinDriftTimeTolerance(observedFeature, targetFeature, driftTimeTolerance); withinTolerances = withinTolerances & (observedFeature.ChargeState == targetFeature.ChargeState); } // Create a temporary match between the two and check it against all tolerances before adding to the match list. if (withinTolerances) { var match = new FeatureMatch <TObserved, TTarget>(); match.AddFeatures(observedFeature, targetFeature, m_matchParameters.UseDriftTime, (shiftAmount > 0)); matchList.Add(match); } } else { // Increase the lower bound if the the MassTag masses are too low or set the continueLoop flag to false if they are too high. if (massDifference < massTolerancePpm) { lowerBound++; } else { continueLoop = false; } } // Increment the target index. targetIndex++; } // Increment the observed index. observedIndex++; } // Return the list of matches. return(matchList); }