/// <summary>
        /// The score feature.
        /// </summary>
        /// <param name="peak">
        /// The peak.
        /// </param>
        /// <param name="globalMaxIntensity">
        /// The global max intensity.
        /// </param>
        /// <param name="uimfReader">
        /// The uimf reader.
        /// </param>
        /// <param name="massToleranceInPpm">
        /// The mass tolerance in ppm.
        /// </param>
        /// <param name="driftTimeToleranceInMs">
        /// The drift time tolerance in ms.
        /// </param>
        /// <param name="voltageGroup">
        /// The voltage group.
        /// </param>
        /// <param name="voltageGroupScans">
        /// The voltage group scans.
        /// </param>
        /// <param name="target">
        /// The target.
        /// </param>
        /// <param name="isotopicScoreMethod">
        /// The isotopic score method.
        /// </param>
        /// <param name="theoreticalIsotopicProfile">
        /// The theoretical isotopic profile.
        /// </param>
        /// <returns>
        /// The <see cref="PeakScores"/>.
        /// </returns>
        public static PeakScores ScoreFeature(this StandardImsPeak peak, double globalMaxIntensity, DataReader uimfReader, double massToleranceInPpm, double driftTimeToleranceInMs, VoltageGroup voltageGroup, int voltageGroupScans, IImsTarget target, IsotopicScoreMethod isotopicScoreMethod, List<Peak> theoreticalIsotopicProfile)
        {
            double intensityScore = IntensityScore(peak, globalMaxIntensity);

            double peakShapeScore = PeakShapeScore(
                peak,
                uimfReader,
                massToleranceInPpm,
                driftTimeToleranceInMs,
                voltageGroup,
                globalMaxIntensity,
                voltageGroupScans);

            double isotopicScore = 0;
            if (target.HasCompositionInfo)
            {
                isotopicScore = IsotopicProfileScore(
                    peak,
                    uimfReader,
                    target,
                    theoreticalIsotopicProfile,
                    voltageGroup,
                    IsotopicScoreMethod.Angle,
                    globalMaxIntensity,
                    voltageGroupScans);
            }

            return new PeakScores(intensityScore, isotopicScore, peakShapeScore);
        }
        /// <summary>
        /// The score feature using isotopic profile.
        /// </summary>
        /// <param name="imsPeak">
        /// The ims Peak.
        /// </param>
        /// <param name="reader">
        /// The reader.
        /// </param>
        /// <param name="target">
        /// The Target.
        /// </param>
        /// <param name="isotopicPeakList">
        /// The isotopic peak list.
        /// </param>
        /// <param name="voltageGroup">
        /// The voltage Group.
        /// </param>
        /// <param name="selectedMethod">
        /// The selected Method.
        /// </param>
        /// <param name="globalMaxIntensities">
        /// </param>
        /// <returns>
        /// The <see cref="double"/>.
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// </exception>
        public static double IsotopicProfileScore(StandardImsPeak imsPeak, DataReader reader, IImsTarget target, List<Peak> isotopicPeakList, VoltageGroup voltageGroup, IsotopicScoreMethod selectedMethod, double globalMaxIntensities, double totalScans)
        {
            // No need to move on if the isotopic profile is not found
            // if (observedIsotopicProfile == null || observedIsotopicProfile.MonoIsotopicMass < 1)
            // {
            // result.AnalysisStatus = AnalysisStatus.IsotopicProfileNotFound;
            // continue;
            // }

            // Find Isotopic Profile
            // List<Peak> massSpectrumPeaks;
            // IsotopicProfile observedIsotopicProfile = _msFeatureFinder.IterativelyFindMSFeature(massSpectrum, theoreticalIsotopicProfile, out massSpectrumPeaks);
            if (target.CompositionWithoutAdduct == null)
            {
                throw new InvalidOperationException("Cannot score feature using isotopic profile for Ims Target without CompositionWithoutAdduct provided.");
            }

            // Bad Feature, so get out
            if (imsPeak == null)
            {
                return 0;
            }

            // Get the scanWindow size
            int scanNumberMax = imsPeak.PeakApex.DriftTimeFullWidthHalfMaxHigherBondInScanNumber;
            int scanNumberMin = imsPeak.PeakApex.DriftTimeFullWidthHalfMaxLowerBondInScanNumber;
            if ((scanNumberMin < 0) || (scanNumberMax > totalScans - 1))
            {
                return 0;
            }

            // Get the mass error from the observed feature peak from the Target theoretical peak
            double mzOffset = imsPeak.PeakApex.MzCenterInDalton - target.MassWithAdduct;

            List<double> observedIsotopicPeakList = new List<double>();

            int totalIsotopicIndex = isotopicPeakList.Count;
            int[] isotopicIndexMask = new int[totalIsotopicIndex];

            // Find an unsaturated peak in the isotopic profile
            for (int i = 0; i < totalIsotopicIndex; i++)
            {
                // Isotopic centerMz
                double Mz = isotopicPeakList[i].XValue;

                var peakList = reader.GetXic(Mz + mzOffset,
                    imsPeak.PeakApex.MzWindowToleranceInPpm,
                    voltageGroup.FirstFrameNumber,
                    voltageGroup.LastFrameNumber,
                    scanNumberMin,
                    scanNumberMax,
                    DataReader.FrameType.MS1,
                    DataReader.ToleranceType.PPM);

                // Sum the intensities
                double sumIntensities = 0;
                foreach (var point in peakList)
                {
                    sumIntensities += point.Intensity;
                    if (point.IsSaturated)
                    {
                        isotopicIndexMask[i] = 1;
                    }
                }

                sumIntensities /= voltageGroup.FrameAccumulationCount;
                observedIsotopicPeakList.Add(sumIntensities);
            }

            // Return 0 if the intensity sum is really small
            if (observedIsotopicPeakList.Sum() < globalMaxIntensities * 0.0003)
            {
                return 0;
            }

            // If the unsaturated isotopes are below a certain threshold
            if (totalIsotopicIndex - isotopicIndexMask.Sum() <= 1)
            {
                return 0;
            }

            if (selectedMethod == IsotopicScoreMethod.Angle)
            {
                return IsotopicProfileScoreAngle(observedIsotopicPeakList, isotopicPeakList);
            }
            else if (selectedMethod == IsotopicScoreMethod.EuclideanDistance)
            {
                return IsotopicProfileScoreEuclidean(observedIsotopicPeakList, isotopicPeakList);
            }
            else if (selectedMethod == IsotopicScoreMethod.PearsonCorrelation)
            {
                return PearsonCorrelation(observedIsotopicPeakList, isotopicPeakList);
            }
            else if (selectedMethod == IsotopicScoreMethod.Bhattacharyya)
            {
                return BhattacharyyaDistance(observedIsotopicPeakList, isotopicPeakList);
            }
            else if (selectedMethod == IsotopicScoreMethod.EuclideanDistanceAlternative)
            {
                return EuclideanAlternative(observedIsotopicPeakList, isotopicPeakList);
            }
            else
            {
                throw new NotImplementedException();
            }
        }