public MsFeatureSpectraViewModel(MSFeatureLight feature, IEnumerable <XYData> spectrum, string name) : base(name) { MsmsDistanceLower = 1.5; MsmsDistanceUpper = 1.5; var mzAxis = new LinearAxis { Position = AxisPosition.Bottom, IsZoomEnabled = true, MinorStep = 1, AbsoluteMinimum = 0 }; var intensityAxis = new LinearAxis { IsPanEnabled = false, Position = AxisPosition.Left, IsZoomEnabled = true, Minimum = 0, AbsoluteMinimum = 0, UseSuperExponentialFormat = true }; Model.Axes.Add(mzAxis); Model.Axes.Add(intensityAxis); m_mzAxis = mzAxis; PlotSpectra(feature, spectrum); }
private MSFeatureLight FindFeature(double x) { MSFeatureLight best = null; if (SelectedCharge == null) { return(null); } if (!m_scanMaps.ContainsKey(SelectedCharge.ChargeState)) { return(best); } var bestDist = double.MaxValue; foreach (var msFeature in m_scanMaps[SelectedCharge.ChargeState]) { var dist = Math.Abs(msFeature.Scan - x); if (!(dist < bestDist)) { continue; } best = msFeature; bestDist = dist; } return(best); }
/// <summary> /// Weighted distance function that was used previously in the old feature finder. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public double WeightedNETDistanceFunction(MSFeatureLight a, MSFeatureLight b) { if ((a.MassMonoisotopic - b.MassMonoisotopic) * m_options.MonoMassWeight > m_options.ConstraintMonoMass || (a.MassMonoisotopicAverage - b.MassMonoisotopicAverage) * m_options.AveMassWeight > m_options.ConstraintAveMass) { return(double.MaxValue); } double a_log_abundance = Math.Log10(a.Abundance); double b_log_abundance = Math.Log10(b.Abundance); double ppm = ((a.MassMonoisotopic - b.MassMonoisotopic) / a.MassMonoisotopic) * 1000000; double ppmAvg = ((a.MassMonoisotopicAverage - b.MassMonoisotopicAverage) / a.MassMonoisotopicAverage) * 1000000; if (!m_options.UseNET) { double sqrDist = ppm * ppm * m_options.MonoMassWeight * m_options.MonoMassWeight; sqrDist += ppmAvg * ppmAvg * m_options.AveMassWeight * m_options.AveMassWeight; sqrDist += (a_log_abundance - b_log_abundance) * (a_log_abundance - b_log_abundance) * m_options.LogAbundanceWeight * m_options.LogAbundanceWeight; sqrDist += (a.Scan - b.Scan) * (a.Scan - b.Scan) * m_options.ScanWeight * m_options.ScanWeight; sqrDist += (a.Score - b.Score) * (a.Score - b.Score) * m_options.FitWeight * m_options.FitWeight; return(Math.Sqrt(sqrDist)); } else { double sqrDist = ppm * ppm * m_options.MonoMassWeight * m_options.MonoMassWeight; double net_distance = Convert.ToDouble(a.Scan - b.Scan) / Convert.ToDouble(m_maxScan - m_minScan); sqrDist += (a_log_abundance - b_log_abundance) * (a_log_abundance - b_log_abundance) * m_options.LogAbundanceWeight * m_options.LogAbundanceWeight; // Convert scan difference to Generic NET sqrDist += net_distance * net_distance * m_options.NETWeight * m_options.NETWeight; sqrDist += (a.Score - b.Score) * (a.Score - b.Score) * m_options.FitWeight * m_options.FitWeight; return(Math.Sqrt(sqrDist)); } }
public MsFeatureSpectraViewModel(MSFeatureLight feature, IEnumerable<XYData> spectrum, string name) : base(name) { MsmsDistanceLower = 1.5; MsmsDistanceUpper = 1.5; var mzAxis = new LinearAxis { Position = AxisPosition.Bottom, IsZoomEnabled = true, MinorStep = 1, AbsoluteMinimum = 0 }; var intensityAxis = new LinearAxis { IsPanEnabled = false, Position = AxisPosition.Left, IsZoomEnabled = true, Minimum = 0, AbsoluteMinimum = 0, UseSuperExponentialFormat = true }; Model.Axes.Add(mzAxis); Model.Axes.Add(intensityAxis); m_mzAxis = mzAxis; PlotSpectra(feature, spectrum); }
public static UMCLight GetParentUmc(this MSFeatureLight feature) { if (feature == null) { return(null); } return(feature.ParentFeature); }
/// <summary> /// Determines if two features are within proper range of each other. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> protected bool WithinRange(MSFeatureLight x, MSFeatureLight y) { double distance = WeightedNETDistanceFunction(x, y); if (Math.Abs(x.Scan - y.Scan) > 6000) { if (distance < m_maxDistance) { int xx = 0; xx++; } } return(distance < m_maxDistance); }
/// <summary> /// Creates an XIC from the m/z values provided. /// </summary> /// <param name="mz"></param> /// <param name="massError"></param> /// <param name="minScan"></param> /// <param name="maxScan"></param> /// <param name="provider"></param> /// <returns></returns> public IEnumerable <MSFeatureLight> CreateXic(double mz, double massError, int minScan, int maxScan, ISpectraProvider provider) { var newFeatures = new List <MSFeatureLight>(); var lower = FeatureLight.ComputeDaDifferenceFromPPM(mz, massError); var higher = FeatureLight.ComputeDaDifferenceFromPPM(mz, -massError); for (var i = minScan; i < maxScan; i++) { List <XYData> spectrum = null; try { var summary = new ScanSummary(); spectrum = provider.GetRawSpectra(i, 0, 1, out summary); } catch { } if (spectrum == null) { continue; } var data = (from x in spectrum where x.X > lower && x.X < higher select x).ToList(); var summedIntensity = data.Sum(x => x.Y); var newFeature = new MSFeatureLight { Scan = i, Net = i, Abundance = Convert.ToInt64(summedIntensity) }; newFeatures.Add(newFeature); } return(newFeatures); }
public List <MSFeatureLight> LoadMSFeaturesFromCache(string path) { var features = new List <MSFeatureLight>(); var start = System.DateTime.Now; using (var connection = new SQLiteConnection("Data Source=" + path)) { connection.Open(); using (var command = connection.CreateCommand()) { command.CommandType = System.Data.CommandType.Text; command.CommandText = "SELECT * FROM T_MSFeatures where DATASET_ID = 0"; using (var reader = command.ExecuteReader()) { var x = 0; var values = new object[100]; while (reader.Read()) { var feature = new MSFeatureLight(); feature.DriftTime = Convert.ToDouble(reader["DriftTime"]); feature.Score = Convert.ToDouble(reader["FIT"]); feature.Scan = Convert.ToInt32(reader["SCAN_NUM"]); feature.ChargeState = Convert.ToInt32(reader["CHARGE"]); feature.Abundance = Convert.ToInt64(reader["ABUNDANCE"]); feature.Mz = Convert.ToDouble(reader["MZ"]); feature.MassMonoisotopicAverage = Convert.ToDouble(reader["AVERAGE_MW"]); feature.MassMonoisotopic = Convert.ToDouble(reader["MONOISOTOPIC_MW"]); feature.MassMonoisotopicMostAbundant = Convert.ToDouble(reader["MONOISOTOPIC_MW_ABUNDANT"]); feature.UmcId = Convert.ToInt32(reader["LCMS_FEATURE_ID"]); x++; features.Add(feature); } System.Console.WriteLine("{0} features loaded", x); } } } var end = System.DateTime.Now; var span = end.Subtract(start); System.Console.WriteLine("{0} features loaded", span.TotalMilliseconds); return(features); }
public List<MSFeatureLight> LoadMSFeaturesFromCache(string path) { var features = new List<MSFeatureLight>(); var start = System.DateTime.Now; using (var connection = new SQLiteConnection("Data Source=" + path)) { connection.Open(); using (var command = connection.CreateCommand()) { command.CommandType = System.Data.CommandType.Text; command.CommandText = "SELECT * FROM T_MSFeatures where DATASET_ID = 0"; using (var reader = command.ExecuteReader()) { var x = 0; var values = new object[100]; while (reader.Read()) { var feature = new MSFeatureLight(); feature.DriftTime = Convert.ToDouble(reader["DriftTime"]); feature.Score = Convert.ToDouble(reader["FIT"]); feature.Scan = Convert.ToInt32(reader["SCAN_NUM"]); feature.ChargeState = Convert.ToInt32(reader["CHARGE"]); feature.Abundance = Convert.ToInt64(reader["ABUNDANCE"]); feature.Mz = Convert.ToDouble(reader["MZ"]); feature.MassMonoisotopicAverage = Convert.ToDouble(reader["AVERAGE_MW"]); feature.MassMonoisotopic = Convert.ToDouble(reader["MONOISOTOPIC_MW"]); feature.MassMonoisotopicMostAbundant = Convert.ToDouble(reader["MONOISOTOPIC_MW_ABUNDANT"]); feature.UmcId = Convert.ToInt32(reader["LCMS_FEATURE_ID"]); x++; features.Add(feature); } System.Console.WriteLine("{0} features loaded", x); } } } var end = System.DateTime.Now; var span = end.Subtract(start); System.Console.WriteLine("{0} features loaded", span.TotalMilliseconds); return features; }
public void TestChargeStateSplit(string path) { var data = File.ReadAllLines(path); var map = new Dictionary <int, List <MSFeatureLight> >(); for (var i = 1; i < data.Length; i++) { var feature = new MSFeatureLight(); var msFeatureData = data[i].Split(','); feature.ChargeState = Convert.ToInt32(msFeatureData[0]); feature.MassMonoisotopic = Convert.ToDouble(msFeatureData[1]); feature.Scan = Convert.ToInt32(msFeatureData[2]); feature.Abundance = Convert.ToInt64(msFeatureData[3]); if (!map.ContainsKey(feature.ChargeState)) { map.Add(feature.ChargeState, new List <MSFeatureLight>()); } map[feature.ChargeState].Add(feature); } var features = new List <UMCLight>(); foreach (var charge in map.Keys) { var feature = new UMCLight(); foreach (var msFeature in map[charge]) { feature.AddChildFeature(msFeature); } feature.CalculateStatistics(ClusterCentroidRepresentation.Median); features.Add(feature); } var finder = new MsFeatureTreeClusterer <MSFeatureLight, UMCLight>(); var comparison = finder.CompareMonoisotopic(features[0], features[1]); Assert.AreNotEqual(comparison, 0); }
public void TestChargeStateSplit(string path) { var data = File.ReadAllLines(path); var map = new Dictionary<int, List<MSFeatureLight>>(); for (var i = 1; i < data.Length; i++) { var feature = new MSFeatureLight(); var msFeatureData = data[i].Split(','); feature.ChargeState = Convert.ToInt32(msFeatureData[0]); feature.MassMonoisotopic = Convert.ToDouble(msFeatureData[1]); feature.Scan = Convert.ToInt32(msFeatureData[2]); feature.Abundance = Convert.ToInt64(msFeatureData[3]); if (!map.ContainsKey(feature.ChargeState)) { map.Add(feature.ChargeState, new List<MSFeatureLight>()); } map[feature.ChargeState].Add(feature); } var features = new List<UMCLight>(); foreach (var charge in map.Keys) { var feature = new UMCLight(); foreach (var msFeature in map[charge]) { feature.AddChildFeature(msFeature); } feature.CalculateStatistics(ClusterCentroidRepresentation.Median); features.Add(feature); } var finder = new MsFeatureTreeClusterer<MSFeatureLight, UMCLight>(); var comparison = finder.CompareMonoisotopic(features[0], features[1]); Assert.AreNotEqual(comparison, 0); }
private void LoadSpectrum(MSFeatureLight msFeature) { var info = SingletonDataProviders.GetDatasetInformation(msFeature.GroupId); if (info == null || info.RawFile.Path == null || info.RawFile.Path == null) { return; } var mz = msFeature.Mz; var charge = msFeature.ChargeState; var spacing = 1.0 / Convert.ToDouble(charge); var lowMz = mz - spacing * 3; var highMz = mz + spacing * (NumberOfIsotopes + 1); var spectrum = ParentSpectraFinder.GetParentSpectrum(info.RawFile.Path, msFeature.Scan, lowMz, highMz); if (spectrum == null) { return; } var name = string.Format("Scan {0} Charge {1} Dataset {2}", msFeature.Scan, msFeature.ChargeState, msFeature.GroupId ); var msFeatureSpectra = new MsFeatureSpectraViewModel(msFeature, spectrum, name); msFeatureSpectra.SetXExtrema(lowMz, highMz); ParentSpectrumViewModel = msFeatureSpectra; }
/// <summary> /// Builds XIC plot based on selected charge state chromatograms. /// </summary> private void BuildPlot() { this.XicPlotModel.Series.Clear(); double minX = double.PositiveInfinity; double maxX = 0; double minY = double.PositiveInfinity; double maxY = 0; var chargeHash = new HashSet <int>(); MSFeatureLight maxFeature = null; int i = 0; foreach (var feature in this.Features) { var xics = this.GetXic(feature.UMCLight); foreach (var xic in xics) { if (xic.Count == 0) { continue; } if (!chargeHash.Contains(xic[0].ChargeState)) { chargeHash.Add(xic[0].ChargeState); } // Get dataset info for mapping scan # -> retention time var dsInfo = SingletonDataProviders.GetDatasetInformation(feature.UMCLight.GroupId); foreach (var msfeature in xic) { minX = Math.Min(minX, msfeature.Net); maxX = Math.Max(maxX, msfeature.Net); minY = Math.Min(minY, msfeature.Abundance); maxY = Math.Max(maxY, msfeature.Abundance); } var maxA = xic.Max(msf => msf.Abundance); var maxL = xic.FirstOrDefault(msf => msf.Abundance.Equals(maxA)); if (maxFeature == null || (maxL != null && maxL.Abundance >= maxFeature.Abundance)) { maxFeature = maxL; } var color = this.Colors[i++ % this.Colors.Count]; var series = new LineSeries { ItemsSource = xic, Mapping = dataPoint => new DataPoint(((MSFeatureLight)dataPoint).Net, ((MSFeatureLight)dataPoint).Abundance), Title = string.Format("{0}({1}+) ID({2})", dsInfo.DatasetName, xic[0].ChargeState, feature.UMCLight.Id), Color = color, MarkerType = MarkerType.Circle, MarkerSize = 3, MarkerFill = OxyColors.White, MarkerStroke = color, MarkerStrokeThickness = 0.5, TrackerFormatString = "{0}" + Environment.NewLine + "{1}: {2:0.###} (Scan: {Scan:0})" + Environment.NewLine + "{3}: {4:0.###E0}" + Environment.NewLine }; this.XicPlotModel.Series.Add(series); } } this.SelectedMsFeature = maxFeature; this.SetMsFeatureAnnotation(); this.ChargeStates.Clear(); foreach (var chargeState in chargeHash) { this.ChargeStates.Add(new ChargeStateViewModel(chargeState)); } minX = Math.Max(0, minX - (0.01 * minX)); maxX = maxX + (0.01 * maxX); maxY = maxY + (0.05 * maxY); this.xaxis.Minimum = minX; this.xaxis.Maximum = maxX; this.yaxis.Minimum = minY; this.yaxis.Maximum = maxY; this.xaxis.Zoom(minX, maxX); this.yaxis.Zoom(minY, maxY); this.XicPlotModel.InvalidatePlot(true); }
public static bool HasMsMs(this MSFeatureLight msFeature) { return(msFeature.MSnSpectra.Count > 0); }
/// <summary> /// Reconstructs a MS Feature by loading the MS/MS data /// </summary> /// <param name="feature"></param> /// <param name="providers"></param> public static void ReconstructMSFeature(this MSFeatureLight msFeature, FeatureDataAccessProviders providers) { // We are reconstruction the objects here. But // I want to reduce the number of transactions to make. // So I go back through the database and pull out all msms spectra first // then sort it out in memory. // Get the map var msmsFeatures = new List <MSFeatureToMSnFeatureMap>(); // Maps the id's of the MS/MS spectra var ids = new List <int>(); // Make a map, from the dataset, then the spectra to the ms feature Id. var map = new Dictionary <int, Dictionary <int, MSFeatureToMSnFeatureMap> >(); msmsFeatures = providers.MSFeatureToMSnFeatureCache.FindByUMCFeatureId(msFeature.GroupId, msFeature.Id); // Then grab the spectra id list ids = msmsFeatures.ConvertAll(x => x.MSMSFeatureID); // construct that map here. foreach (var subFeature in msmsFeatures) { // first map the dataset id if (!map.ContainsKey(subFeature.MSDatasetID)) { map.Add(subFeature.MSDatasetID, new Dictionary <int, MSFeatureToMSnFeatureMap>()); } //TODO: There may be multiple MSMS spectra // Then map its msms spectra id if (map[subFeature.MSDatasetID].ContainsKey(subFeature.MSFeatureID)) { continue; } map[subFeature.MSDatasetID].Add(subFeature.MSFeatureID, subFeature); } // Now we get all the spectra, map to the UMC, then the ms/ms spectra. var spectra = providers.MSnFeatureCache.FindBySpectraId(ids); var spectraMap = new Dictionary <int, Dictionary <int, MSSpectra> >(); foreach (var spectrum in spectra) { if (!spectraMap.ContainsKey(spectrum.GroupId)) { spectraMap.Add(spectrum.GroupId, new Dictionary <int, MSSpectra>()); } spectraMap[spectrum.GroupId].Add(spectrum.Id, spectrum); } // Here we check the dataset. if (map.ContainsKey(msFeature.GroupId)) { // then check the ms/ms spectra if (map[msFeature.GroupId].ContainsKey(msFeature.Id)) { // ok, we are sure that the spectra is present now! var singleMap = map[msFeature.GroupId][msFeature.Id]; var spectrum = spectraMap[singleMap.MSDatasetID][singleMap.MSMSFeatureID]; msFeature.MSnSpectra.Add(spectrum); } } }
public IEnumerable <UMCLight> CreateXic(IList <UMCLight> features, double massError, ISpectraProvider provider) { // this algorithm works as follows // // PART A - Build the XIC target list // For each UMC Light , find the XIC representation // for each charge in a feature // from start scan to end scan // 1. Compute a lower / upper m/z bound // 2. build an XIC chomatogram object // 3. reference the original UMC Feature -- this allows us to easily add // chromatograms to the corresponding feature // 4. store the chomatogram (with unique ID across all features) // // PART B - Read Data From File // Sort the list of XIC's by scan // for each scan s = start scan to end scan // 1. find all xic's that start before and end after s - // a. cache these xics in a dictionary based on unique id // b. NOTE: this is why we sort so we can do an O(N) search for // all XIC's that need data from this scan s // 2. Then for each XIC that needs data // a. Pull intensity data from lower / upper m/z bound // b. create an MS Feature // c. store in original UMC Feature // d. Test to see if the XIC is done building (Intensity < 1 or s > scan end) // 3. Remove features that are done building from cache // // CONCLUSIONS // Building UMC's then takes linear time (well O(N Lg N) time if you consider sort) // and theoretically is only bounded by the time it takes to read an entire raw file // if (features.Count <= 0) { throw new Exception("No features were available to create XIC's from"); } var minScan = Math.Max(1, features.Min(x => x.Scan - ScanWindowSize)); var maxScan = features.Max(x => x.Scan + ScanWindowSize); OnProgress("Sorting features for optimized scan partitioning"); // PART A // Map the feature ID to the xic based features var xicFeatures = new SortedSet <XicFeature>(); var allFeatures = CreateXicTargets(features, massError); // PART B // sort the features... var featureCount = allFeatures.Count; allFeatures = allFeatures.OrderBy(x => x.StartScan).ToList(); // This map tracks all possible features to keep var msFeatureId = 0; // This list stores a temporary amount of parent MS features // so that we can link MS/MS spectra to MS Features var parentMsList = new List <MSFeatureLight>(); // Creates a comparison function for building a BST from a spectrum. var msmsFeatureId = 0; var totalScans = provider.GetTotalScans(0); OnProgress(string.Format("Analyzing {0} scans", totalScans)); // Iterate over all the scans... for (var currentScan = minScan; currentScan < maxScan && currentScan <= totalScans; currentScan++) { // Find any features that need data from this scan var featureIndex = 0; while (featureIndex < featureCount) { var xicFeature = allFeatures[featureIndex]; // This means that no new features were eluting with this scan.... if (xicFeature.StartScan > currentScan) { break; } // This means that there is a new feature... if (currentScan <= xicFeature.EndScan) { if (!xicFeatures.Contains(xicFeature)) { xicFeatures.Add(xicFeature); } } featureIndex++; } // Skip pulling the data from the file if there is nothing to pull from. if (xicFeatures.Count < 1) { continue; } // Here We link the MSMS Spectra to the UMC Features ScanSummary summary; var spectrum = provider.GetRawSpectra(currentScan, 0, 1, out summary); if (summary.MsLevel > 1) { // If it is an MS 2 spectra... then let's link it to the parent MS // Feature var matching = parentMsList.Where( x => Math.Abs(x.Mz - summary.PrecursorMz) <= FragmentationSizeWindow ); foreach (var match in matching) { // We create multiple spectra because this guy is matched to multiple ms // features var spectraData = new MSSpectra { Id = msmsFeatureId, ScanMetaData = summary, CollisionType = summary.CollisionType, Scan = currentScan, MsLevel = summary.MsLevel, PrecursorMz = summary.PrecursorMz, TotalIonCurrent = summary.TotalIonCurrent }; match.MSnSpectra.Add(spectraData); spectraData.ParentFeature = match; } if (spectrum != null) { spectrum.Clear(); } msmsFeatureId++; continue; } var mzList = new double[spectrum.Count]; var intensityList = new double[spectrum.Count]; XYData.XYDataListToArrays(spectrum, mzList, intensityList); Array.Sort(mzList, intensityList); // Tracks which spectra need to be removed from the cache var toRemove = new List <XicFeature>(); // Tracks which features we need to link to MSMS spectra with parentMsList.Clear(); // now we iterate through all features that need data from this scan foreach (var xic in xicFeatures) { var lower = xic.LowMz; var higher = xic.HighMz; var startIndex = Array.BinarySearch(mzList, lower); // A bitwise complement of the index, so use the bitwise complement if (startIndex < 0) { startIndex = ~startIndex; } double summedIntensity = 0; if (startIndex < mzList.Count() && mzList[startIndex] < lower) { // All data in the list is lighter than lower; nothing to sum } else { while (startIndex < mzList.Count() && mzList[startIndex] <= higher) { summedIntensity += intensityList[startIndex]; startIndex++; } } // See if we need to remove this feature // We only do so if the intensity has dropped off and we are past the end of the feature. if (summedIntensity < 1 && currentScan > xic.EndScan) { toRemove.Add(xic); continue; } var umc = xic.Feature; // otherwise create a new feature here... var msFeature = new MSFeatureLight { ChargeState = xic.ChargeState, Mz = xic.Mz, MassMonoisotopic = umc.MassMonoisotopic, Scan = currentScan, Abundance = Convert.ToInt64(summedIntensity), Id = msFeatureId++, DriftTime = umc.DriftTime, Net = currentScan, GroupId = umc.GroupId }; parentMsList.Add(msFeature); xic.Feature.AddChildFeature(msFeature); } // Remove features that end their elution prior to the current scan toRemove.ForEach(x => xicFeatures.Remove(x)); } OnProgress("Filtering bad features with no data."); features = features.Where(x => x.MsFeatures.Count > 0).ToList(); OnProgress("Refining XIC features."); return(RefineFeatureXics(features)); }
/// <summary> /// Aligns features based on MSMS spectral similarity. /// </summary> /// <param name="featureMap"></param> /// <param name="msms"></param> public List <MsmsCluster> Cluster(List <UMCLight> features, ISpectraProvider provider) { UpdateStatus("Mapping UMC's to MS/MS spectra using intensity profile."); // Step 1: Cluster the spectra // Create the collection of samples. var msFeatures = new List <MSFeatureLight>(); // Sort through the features foreach (var feature in features) { // Sort out charge states...? var chargeMap = new Dictionary <int, MSFeatureLight>(); double abundance = int.MinValue; MSFeatureLight maxFeature = null; // Find the max abundance spectrum. This the number of features we have to search. foreach (var msFeature in feature.MsFeatures) { if (msFeature.Abundance > abundance && msFeature.MSnSpectra.Count > 0) { abundance = msFeature.Abundance; maxFeature = msFeature; } } if (maxFeature != null) { msFeatures.Add(maxFeature); } } UpdateStatus(string.Format("Found {0} total spectra for clustering.", msFeatures.Count)); UpdateStatus("Sorting spectra."); // Sort based on mass using the max abundance of the feature. msFeatures.Sort(delegate(MSFeatureLight x, MSFeatureLight y) { return(x.MassMonoisotopicMostAbundant.CompareTo(y.MassMonoisotopicMostAbundant)); }); // Then cluster the spectra. var j = 1; var h = 0; var N = msFeatures.Count; var clusters = new List <MsmsCluster>(); var tol = MassTolerance; var lastTotal = 0; UpdateStatus("Clustering spectra."); while (j < N) { var i = j - 1; var featureJ = msFeatures[j]; var featureI = msFeatures[i]; var diff = FeatureLight.ComputeMassPPMDifference(featureJ.MassMonoisotopicMostAbundant, featureI.MassMonoisotopicMostAbundant); if (Math.Abs(diff) > tol) { // We only care to create clusters of size greater than one. if ((j - h) > 1) { var data = Cluster(h, j, msFeatures, provider, SimilarityTolerance); clusters.AddRange(data); } // Reset the count, we're done looking at those clusters. h = j; } if (j - lastTotal > 500) { lastTotal = j; UpdateStatus(string.Format("Processed {0} / {1} total spectra.", lastTotal, N)); } j++; } UpdateStatus("Finishing last cluster data."); // Cluster the rest if ((j - h) > 1) { var data = Cluster(h, j, msFeatures, provider, SimilarityTolerance); clusters.AddRange(data); } UpdateStatus("Finished clustering."); var passingClusters = clusters.Where(cluster => cluster.Features.Count >= MinimumClusterSize); return(passingClusters.ToList()); }
/// <summary> /// Plots the UMC's /// </summary> /// <param name="features"></param> private void PlotFeatures(IEnumerable <UMCLight> features) { var markerIterator = new MarkerTypeIterator(); m_colorIterator = new ColorTypeIterator(); var i = 0; m_scanAnnotation = new LineAnnotation { X = 0, TextColor = OxyColors.Gray, Text = "0", TextOrientation = AnnotationTextOrientation.Vertical, LineStyle = LineStyle.Dash, Type = LineAnnotationType.Vertical, }; Model.Annotations.Add(m_scanAnnotation); foreach (var feature in features) { var chargeMap = feature.CreateChargeMap(); foreach (var charge in chargeMap.Keys) { var msFeatures = chargeMap[charge]; msFeatures = msFeatures.OrderBy(x => x.Scan).ToList(); var mz = msFeatures[0].Mz; var newSeries = new LineSeries { Color = m_colorIterator.GetColor(charge), MarkerFill = m_colorIterator.GetColor(charge), MarkerSize = 3, MarkerStroke = OxyColors.White, MarkerStrokeThickness = 1.5, MarkerType = markerIterator.GetMarker(i++), Title = string.Format("{0} m/z - Charge {1}", mz.ToString("F3"), charge) }; double abundance = 0; MSFeatureLight bestFeature = null; foreach (var msFeature in msFeatures) { if (abundance < msFeature.Abundance) { bestFeature = msFeature; abundance = msFeature.Abundance; } foreach (var msms in msFeature.MSnSpectra) { var peptideSequence = ""; if (msms.Peptides.Count > 0) { peptideSequence = msms.Peptides[0].Sequence; } var msmsAnnotation = new LineAnnotation { Type = LineAnnotationType.Vertical, X = msms.Scan, Y = msFeature.Abundance, StrokeThickness = 2, Color = m_colorIterator.GetColor(msFeature.ChargeState), TextColor = m_colorIterator.GetColor(msFeature.ChargeState), Text = string.Format("{2} - {0} m/z {1}", msms.PrecursorMz.ToString("F3"), peptideSequence, msms.CollisionType) }; Model.Annotations.Add(msmsAnnotation); } newSeries.Points.Add(new DataPoint(msFeature.Scan, msFeature.Abundance)); } newSeries.Tag = charge; if (bestFeature != null) { ScanAnnotationX = bestFeature.Scan; SelectedCharge = charge; } Model.Series.Add(newSeries); } } }
public void PlotSpectra(MSFeatureLight feature, IEnumerable <XYData> spectrum) { var series = new StemSeries { Color = OxyColors.Black }; var minimumMz = double.MaxValue; var maximumMz = double.MinValue; var maxAbundance = double.MinValue; if (spectrum.Count() < 1) { return; } foreach (var peak in spectrum) { minimumMz = Math.Min(peak.X, minimumMz); maximumMz = Math.Max(peak.X, maximumMz); maxAbundance = Math.Max(maxAbundance, peak.Y); series.Points.Add(new DataPoint(peak.X, peak.Y)); } var maxAbundanceTop = maxAbundance * .5; Model.Axes[0].AbsoluteMinimum = minimumMz; Model.Axes[0].AbsoluteMaximum = maximumMz; Model.Series.Add(series); // Add in the monoisotopic peak var colors = new ColorTypeIterator(); var chargeColor = colors.GetColor(feature.ChargeState); var msFeature = new StemSeries { Color = chargeColor }; msFeature.Points.Add(new DataPoint(feature.Mz, feature.Abundance)); Model.Series.Add(msFeature); // Add in the rest of the isotopes var alphaColor = OxyColor.FromAColor(100, OxyColors.Red); var charge = feature.ChargeState; var mz = feature.Mz; var abundance = Convert.ToDouble(feature.Abundance); var monoPeakAnnotation = new LineAnnotation { Type = LineAnnotationType.Vertical, X = mz, Color = alphaColor, TextColor = alphaColor, Text = string.Format("mono peak: {0} m/z", mz.ToString("F3")) }; Model.Annotations.Add(monoPeakAnnotation); var lastMz = mz; var spacing = 1.0 / charge; while (mz < maximumMz && abundance > 1) { mz = mz + (1.0 / charge); abundance *= .75; var peakAnnotation = new LineAnnotation { Type = LineAnnotationType.Vertical, X = mz, Color = alphaColor, TextColor = alphaColor, Text = string.Format("{0} m/z", mz.ToString("F3")) }; var spaceAnnotation = new LineAnnotation { Type = LineAnnotationType.Horizontal, Color = alphaColor, TextColor = alphaColor, TextHorizontalAlignment = HorizontalAlignment.Center, TextVerticalAlignment = VerticalAlignment.Top, TextPosition = new DataPoint(.5, 0), MinimumX = lastMz, MaximumX = mz, Text = string.Format("d={0}", spacing.ToString("F2")), Y = maxAbundance * .75 }; maxAbundance *= .75; lastMz = mz; Model.Annotations.Add(spaceAnnotation); Model.Annotations.Add(peakAnnotation); } if (feature.GetParentFeature() != null) { var features = feature.GetParentFeature().Features; foreach (var subFeature in features) { var msms = subFeature.MSnSpectra.Where(x => x.PrecursorMz > minimumMz && x.PrecursorMz < maximumMz); foreach (var fragmentation in msms) { var spaceAnnotation = new LineAnnotation { Type = LineAnnotationType.Vertical, Color = OxyColors.Gray, TextColor = OxyColors.Gray, FontWeight = 3, TextVerticalAlignment = VerticalAlignment.Top, TextPosition = new DataPoint(1, 0), StrokeThickness = 2, Text = string.Format("msms {0} - scan {1}", fragmentation.PrecursorMz.ToString("F2"), fragmentation.Scan), X = fragmentation.PrecursorMz }; Model.Annotations.Add(spaceAnnotation); var lowerMz = new LineAnnotation { Type = LineAnnotationType.Horizontal, Color = OxyColors.LightGray, TextColor = OxyColors.LightGray, FontWeight = 3, TextVerticalAlignment = VerticalAlignment.Top, TextPosition = new DataPoint(1, 0), StrokeThickness = 2, Y = maxAbundanceTop, Text = string.Format("{0} m/z", MsmsDistanceLower.ToString("F2")), MinimumX = fragmentation.PrecursorMz - MsmsDistanceLower, MaximumX = fragmentation.PrecursorMz }; var upperMz = new LineAnnotation { Type = LineAnnotationType.Horizontal, Color = OxyColors.LightGray, TextColor = OxyColors.LightGray, FontWeight = 3, TextVerticalAlignment = VerticalAlignment.Top, TextPosition = new DataPoint(1, 0), StrokeThickness = 2, Text = string.Format("{0} m/z", MsmsDistanceUpper.ToString("F2")), Y = maxAbundanceTop, MinimumX = fragmentation.PrecursorMz, MaximumX = fragmentation.PrecursorMz + MsmsDistanceUpper }; Model.Annotations.Add(upperMz); Model.Annotations.Add(lowerMz); } } } }
/// <summary> /// Determines if two features are within proper range of each other. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> protected bool WithinRange(MSFeatureLight x, MSFeatureLight y) { double distance = WeightedNETDistanceFunction(x, y); if (Math.Abs(x.Scan - y.Scan) > 6000) { if (distance < m_maxDistance) { int xx = 0; xx++; } } return (distance < m_maxDistance); }
/// <summary> /// Weighted distance function that was used previously in the old feature finder. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public double WeightedNETDistanceFunction(MSFeatureLight a, MSFeatureLight b) { if ((a.MassMonoisotopic - b.MassMonoisotopic) * m_options.MonoMassWeight > m_options.ConstraintMonoMass || (a.MassMonoisotopicAverage - b.MassMonoisotopicAverage) * m_options.AveMassWeight > m_options.ConstraintAveMass) { return double.MaxValue; } double a_log_abundance = Math.Log10(a.Abundance); double b_log_abundance = Math.Log10(b.Abundance); double ppm = ((a.MassMonoisotopic - b.MassMonoisotopic) / a.MassMonoisotopic) * 1000000; double ppmAvg = ((a.MassMonoisotopicAverage - b.MassMonoisotopicAverage) / a.MassMonoisotopicAverage) * 1000000; if (!m_options.UseNET) { double sqrDist = ppm * ppm * m_options.MonoMassWeight * m_options.MonoMassWeight; sqrDist += ppmAvg * ppmAvg * m_options.AveMassWeight * m_options.AveMassWeight; sqrDist += (a_log_abundance - b_log_abundance) * (a_log_abundance - b_log_abundance) * m_options.LogAbundanceWeight * m_options.LogAbundanceWeight; sqrDist += (a.Scan - b.Scan) * (a.Scan - b.Scan) * m_options.ScanWeight * m_options.ScanWeight; sqrDist += (a.Score - b.Score) * (a.Score - b.Score) * m_options.FitWeight * m_options.FitWeight; return Math.Sqrt(sqrDist); } else { double sqrDist = ppm * ppm * m_options.MonoMassWeight * m_options.MonoMassWeight; double net_distance = Convert.ToDouble(a.Scan - b.Scan) / Convert.ToDouble(m_maxScan - m_minScan); sqrDist += (a_log_abundance - b_log_abundance) * (a_log_abundance - b_log_abundance) * m_options.LogAbundanceWeight * m_options.LogAbundanceWeight; // Convert scan difference to Generic NET sqrDist += net_distance * net_distance * m_options.NETWeight * m_options.NETWeight; sqrDist += (a.Score - b.Score) * (a.Score - b.Score) * m_options.FitWeight * m_options.FitWeight; return Math.Sqrt(sqrDist); } }
public void PlotSpectra(MSFeatureLight feature, IEnumerable<XYData> spectrum) { var series = new StemSeries { Color = OxyColors.Black }; var minimumMz = double.MaxValue; var maximumMz = double.MinValue; var maxAbundance = double.MinValue; if (spectrum.Count() < 1) return; foreach (var peak in spectrum) { minimumMz = Math.Min(peak.X, minimumMz); maximumMz = Math.Max(peak.X, maximumMz); maxAbundance = Math.Max(maxAbundance, peak.Y); series.Points.Add(new DataPoint(peak.X, peak.Y)); } var maxAbundanceTop = maxAbundance*.5; Model.Axes[0].AbsoluteMinimum = minimumMz; Model.Axes[0].AbsoluteMaximum = maximumMz; Model.Series.Add(series); // Add in the monoisotopic peak var colors = new ColorTypeIterator(); var chargeColor = colors.GetColor(feature.ChargeState); var msFeature = new StemSeries { Color = chargeColor }; msFeature.Points.Add(new DataPoint(feature.Mz, feature.Abundance)); Model.Series.Add(msFeature); // Add in the rest of the isotopes var alphaColor = OxyColor.FromAColor(100, OxyColors.Red); var charge = feature.ChargeState; var mz = feature.Mz; var abundance = Convert.ToDouble(feature.Abundance); var monoPeakAnnotation = new LineAnnotation { Type = LineAnnotationType.Vertical, X = mz, Color = alphaColor, TextColor = alphaColor, Text = string.Format("mono peak: {0} m/z", mz.ToString("F3")) }; Model.Annotations.Add(monoPeakAnnotation); var lastMz = mz; var spacing = 1.0/charge; while (mz < maximumMz && abundance > 1) { mz = mz + (1.0/charge); abundance *= .75; var peakAnnotation = new LineAnnotation { Type = LineAnnotationType.Vertical, X = mz, Color = alphaColor, TextColor = alphaColor, Text = string.Format("{0} m/z", mz.ToString("F3")) }; var spaceAnnotation = new LineAnnotation { Type = LineAnnotationType.Horizontal, Color = alphaColor, TextColor = alphaColor, TextHorizontalAlignment = HorizontalAlignment.Center, TextVerticalAlignment = VerticalAlignment.Top, TextPosition = new DataPoint(.5, 0), MinimumX = lastMz, MaximumX = mz, Text = string.Format("d={0}", spacing.ToString("F2")), Y = maxAbundance*.75 }; maxAbundance *= .75; lastMz = mz; Model.Annotations.Add(spaceAnnotation); Model.Annotations.Add(peakAnnotation); } if (feature.ParentFeature != null) { var features = feature.ParentFeature.Features; foreach (var subFeature in features) { var msms = subFeature.MSnSpectra.Where(x => x.PrecursorMz > minimumMz && x.PrecursorMz < maximumMz); foreach (var fragmentation in msms) { var spaceAnnotation = new LineAnnotation { Type = LineAnnotationType.Vertical, Color = OxyColors.Gray, TextColor = OxyColors.Gray, FontWeight = 3, TextVerticalAlignment = VerticalAlignment.Top, TextPosition = new DataPoint(1, 0), StrokeThickness = 2, Text = string.Format("msms {0} - scan {1}", fragmentation.PrecursorMz.ToString("F2"), fragmentation.Scan), X = fragmentation.PrecursorMz }; Model.Annotations.Add(spaceAnnotation); var lowerMz = new LineAnnotation { Type = LineAnnotationType.Horizontal, Color = OxyColors.LightGray, TextColor = OxyColors.LightGray, FontWeight = 3, TextVerticalAlignment = VerticalAlignment.Top, TextPosition = new DataPoint(1, 0), StrokeThickness = 2, Y = maxAbundanceTop, Text = string.Format("{0} m/z", MsmsDistanceLower.ToString("F2")), MinimumX = fragmentation.PrecursorMz - MsmsDistanceLower, MaximumX = fragmentation.PrecursorMz }; var upperMz = new LineAnnotation { Type = LineAnnotationType.Horizontal, Color = OxyColors.LightGray, TextColor = OxyColors.LightGray, FontWeight = 3, TextVerticalAlignment = VerticalAlignment.Top, TextPosition = new DataPoint(1, 0), StrokeThickness = 2, Text = string.Format("{0} m/z", MsmsDistanceUpper.ToString("F2")), Y = maxAbundanceTop, MinimumX = fragmentation.PrecursorMz, MaximumX = fragmentation.PrecursorMz + MsmsDistanceUpper }; Model.Annotations.Add(upperMz); Model.Annotations.Add(lowerMz); } } } }
private void LoadSpectrum(MSFeatureLight msFeature) { var info = SingletonDataProviders.GetDatasetInformation(msFeature.GroupId); if (info == null || info.Raw == null || info.RawPath == null) return; var mz = msFeature.Mz; var charge = msFeature.ChargeState; var spacing = 1.0 / Convert.ToDouble(charge); var lowMz = mz - spacing * 3; var highMz = mz + spacing * (NumberOfIsotopes + 1); var spectrum = ParentSpectraFinder.GetParentSpectrum(info.RawPath, msFeature.Scan, lowMz, highMz); if (spectrum == null) return; var name = string.Format("Scan {0} Charge {1} Dataset {2}", msFeature.Scan, msFeature.ChargeState, msFeature.GroupId ); var msFeatureSpectra = new MsFeatureSpectraViewModel(msFeature, spectrum, name); msFeatureSpectra.SetXExtrema(lowMz, highMz); ParentSpectrumViewModel = msFeatureSpectra; }