/// <summary> /// Get the cosine score for the provided experimental and theoretical peaks /// </summary> /// <param name="spec"></param> /// <param name="isoProfile"></param> /// <param name="comparer"></param> /// <returns></returns> public static double GetCosine(IList <Peak> spec, IList <Peak> isoProfile, IComparer <Peak> comparer) { var numPeaksSpec = spec.Count; var numTheoProfilePeaks = isoProfile.Count; var index1 = 0; var index2 = 0; var theoIntensities = isoProfile.Select(p => p.Intensity).ToArray(); var observedIntensities = new double[numTheoProfilePeaks]; while (index1 < numPeaksSpec && index2 < numTheoProfilePeaks) { var comp = comparer.Compare(spec[index1], isoProfile[index2]); if (comp < 0) { ++index1; } else if (comp > 0) { ++index2; } else { if (spec[index1].Intensity > observedIntensities[index2]) { observedIntensities[index2] = spec[index1].Intensity; } ++index1; //++index2; } } return(FitScoreCalculator.GetCosine(theoIntensities, observedIntensities)); }
/// <summary> /// Try to find the best concentration of the selected isotope /// by stepping through the concentrations and fitting a theoretical /// isotopic profile to the provided observed peaks. /// </summary> /// <param name="progress">The progress reporter.</param> public IsotopeConcentrationCorrelationCurve Tune(IProgress <PRISM.ProgressData> progress = null) { // Set up progress reporter var progressData = new PRISM.ProgressData(progress); ValidateParameters(); // Get default proportions for the selected element. // Copy it to a new array so we can manipulate it. var proportions = GetDefaultProportions(Element).ToArray(); // Make sure this is an isotope we know about and that it isn't the monoisotope if (IsotopeIndex < 1 || IsotopeIndex >= proportions.Length) { throw new ArgumentOutOfRangeException(nameof(IsotopeIndex)); } var defaultProportion = proportions[IsotopeIndex]; // Set the default best point (the first one). var results = new IsotopeConcentrationCorrelationCurve { BestConcentration = new IsotopeConcentrationCorrelationCurve.ConcentrationCorrelationPoint { IsotopeConcentration = defaultProportion, MonoisotopeConcentration = proportions[0], PearsonCorrelation = 0.0 } }; // Iterate over concentration values var numberOfSteps = (int)(MaxConcentration - defaultProportion / StepSize); for (var i = 0; i <= numberOfSteps; i++) { // Update percent complete progressData.Report(i, numberOfSteps); // Calculate concentration var concentrationStep = i * StepSize; proportions[IsotopeIndex] += concentrationStep; // Increase isotope of interest proportions[0] -= concentrationStep; // Decrease monoisotope // Get theoretical isotope profile and align the observed peaks to it var theoreticalIsotopeProfile = GetTheoreticalIsotopeProfile(proportions); var alignedObservedPeaks = AlignObservedPeaks(ObservedPeaks, theoreticalIsotopeProfile, Tolerance); // Break out the intensities of the isotope profiles var theoIntensities = theoreticalIsotopeProfile.Select(peak => peak.Intensity).ToArray(); var obsIntensities = alignedObservedPeaks.Select(peak => peak.Intensity).ToArray(); // Compute pearson correlation var pearsonCorrelation = FitScoreCalculator.GetPearsonCorrelation(obsIntensities, theoIntensities); // Add data point for this concentration to result curve var dataPoint = new IsotopeConcentrationCorrelationCurve.ConcentrationCorrelationPoint { IsotopeConcentration = proportions[IsotopeIndex], MonoisotopeConcentration = proportions[0], PearsonCorrelation = pearsonCorrelation }; results.DataPoints.Add(dataPoint); // If this concentration has a better fit, update the stored results if (pearsonCorrelation >= results.BestConcentration.PearsonCorrelation) { results.BestConcentration = dataPoint; } } return(results); }