/// <summary> /// Create XICs for clusters. (Each XIC point becomes a new MSFeature, // replacing the previous MSFeatures). /// </summary> /// <param name="progress">The progress reporter.</param> /// <param name="umcLights"></param> /// <returns></returns> private List <UMCLight> CreateXics(List <UMCLight> umcLights, IProgress <ProgressData> progress) { var xicCreator = new XicCreator { XicRefiner = new XicRefiner(this.options.XicRelativeIntensityThreshold) }; return(xicCreator.CreateXicNew( umcLights, this.options.InstrumentTolerances.Mass, provider as InformedProteomicsReader, this.options.RefineXics, progress).ToList()); }
/// <summary> /// Finds LCMS Features from MS Features. /// </summary> /// <param name="rawMsFeatures"></param> /// <returns></returns> public List <TParentFeature> Cluster(List <TChildFeature> rawMsFeatures) { Comparison <TChildFeature> mzSort = (x, y) => x.Mz.CompareTo(y.Mz); Comparison <TParentFeature> monoSort = (x, y) => x.MassMonoisotopic.CompareTo(y.MassMonoisotopic); Func <TChildFeature, TChildFeature, double> mzDiff = (x, y) => FeatureLight.ComputeMassPPMDifference(x.Mz, y.Mz); Func <TParentFeature, TParentFeature, double> monoDiff = (x, y) => FeatureLight.ComputeMassPPMDifference(x.MassMonoisotopic, y.MassMonoisotopic); var minScan = Convert.ToDouble(rawMsFeatures.Min(x => x.Scan)); var maxScan = Convert.ToDouble(rawMsFeatures.Max(x => x.Scan)); foreach (var msFeature in rawMsFeatures) { msFeature.Net = (Convert.ToDouble(msFeature.Scan) - minScan) / (maxScan - minScan); } OnProgress("Filtering ambiguous features"); //rawMsFeatures = FilterMsFeatures(rawMsFeatures); OnProgress("Clustering child features into potential UMC candidates"); // First cluster based on m/z finding the XIC's var features = Cluster <TChildFeature, TParentFeature>(rawMsFeatures, mzSort, mzDiff, CompareMz, Tolerances.Mass); var n = features.Count(); OnProgress(string.Format("Found {0} unique child features from {1} total features", n, rawMsFeatures.Count())); OnProgress("Filtering Features"); // Then we group into UMC's for clustering across charge states... if (features == null) { throw new InvalidDataException("No features were found from the input MS Feature list."); } OnProgress("Filtering poor features with no data. Calculating statistics for the good ones."); features = features.Where(x => x.MsFeatures.Count > 0).ToList(); foreach (var feature in features) { feature.CalculateStatistics(ClusterCentroidRepresentation.Median); feature.MassMonoisotopic = (feature.Mz * feature.ChargeState) - (SubAtomicParticleLibrary.MASS_PROTON * feature.ChargeState); } // Here we should merge the XIC data...trying to find the best possible feature // Note that at this point we dont have UMC's. We only have features // that are separated by mass , scan , and charge // so this method should interrogate each one of these.... if (SpectraProvider != null) { OnProgress(string.Format("Building XIC's from child features")); var generator = new XicCreator(); generator.Progress += generator_Progress; features = generator.CreateXic(features as List <UMCLight>, Tolerances.Mass, SpectraProvider) as IEnumerable <TParentFeature>; generator.Progress -= generator_Progress; } OnProgress(string.Format("Calculating statistics for each feature")); foreach (var feature in features) { feature.CalculateStatistics(ClusterCentroidRepresentation.Median); feature.Net = Convert.ToDouble(feature.Scan - minScan) / Convert.ToDouble(maxScan - minScan); } OnProgress(string.Format("Combining child feature charge states")); features = Cluster <TParentFeature, TParentFeature>(features, monoSort, monoDiff, CompareMonoisotopic, Tolerances.Mass); var id = 0; OnProgress(string.Format("Assigning unique feature id's to each feature.")); var featureList = features.ToList(); foreach (var feature in featureList) { feature.Id = id++; } return(featureList); }