/// <summary>
        /// Initializes a new instance of the <see cref="DriftTimeTarget"/> class with H+ as default
        /// ionization, which is a default for peptides.
        /// </summary>
        /// <param name="libraryEntryName">
        /// The library Entry Name.
        /// </param>
        /// <param name="normalizedDriftTimeInMs">
        /// The drift time.
        /// </param>
        /// <param name="peptide">
        /// The peptide.
        /// </param>
        /// <param name="chargeState">
        /// The charge State.
        /// </param>
        public DriftTimeTarget(string libraryEntryName, double normalizedDriftTimeInMs, PeptideTarget peptide, int chargeState = 1)
            : base(peptide.EmpiricalFormula, IonizationMethod.Protonated, libraryEntryName, chargeState)
        {
            peptide.DriftTimeTargetList.Add(this);

            this.NormalizedDriftTimeInMs = normalizedDriftTimeInMs;
            this.TargetType = TargetType.MoleculeWithKnownDriftTime;
        }
        public void AppendResultsOfTargetToCsv(PeptideTarget target)
        {
            string modificationString = "";
            foreach (var modification in target.ModificationList)
            {
                modificationString += modification.Name + ":" + modification.AccessionNum + ";";
            }

            StringBuilder peptideInfo = new StringBuilder();
            peptideInfo.Append(target.ID + ",");
            peptideInfo.Append(target.PeptideSequence + ",");
            peptideInfo.Append(modificationString + ","); // TODO: Mods
            peptideInfo.Append(target.EmpiricalFormula + ",");
            peptideInfo.Append(target.MonoisotopicMass + ",");

            double targetElutionTime = target.NormalizedElutionTime;

            foreach (LcImsTargetResult result in target.ResultList)
            {
                int chargeState = result.ChargeState;
                IEnumerable<DriftTimeTarget> possibleDriftTimeTargets = target.DriftTimeTargetList.Where(x => x.ChargeState == chargeState).OrderBy(x => Math.Abs(x.NormalizedDriftTimeInMs - result.DriftTime));

                double targetDriftTime = 0;
                double driftTimeError = 0;

                if (possibleDriftTimeTargets.Any())
                {
                    DriftTimeTarget driftTimeTarget = possibleDriftTimeTargets.First();
                    targetDriftTime = driftTimeTarget.NormalizedDriftTimeInMs;
                    driftTimeError = result.DriftTime - targetDriftTime;
                }

                double observedMz = result.IsotopicProfile != null ? result.IsotopicProfile.MonoPeakMZ : 0;
                double abundance = result.IsotopicProfile != null ? result.IsotopicProfile.GetAbundance() : 0;
                double elutionTimeError = result.NormalizedElutionTime - targetElutionTime;
                double correlationAverage = 0;

                StringBuilder resultInfo = new StringBuilder();
                resultInfo.Append(result.ChargeState + ",");
                resultInfo.Append(observedMz + ",");
                resultInfo.Append(result.PpmError + ",");
                resultInfo.Append(result.ScanLcRep + ",");
                resultInfo.Append(result.IsotopicFitScore + ",");
                resultInfo.Append(abundance + ",");
                resultInfo.Append(targetElutionTime + ",");
                resultInfo.Append(result.NormalizedElutionTime + ",");
                resultInfo.Append(elutionTimeError + ",");
                resultInfo.Append(targetDriftTime + ",");
                resultInfo.Append(result.DriftTime + ",");
                resultInfo.Append(driftTimeError + ",");
                resultInfo.Append(correlationAverage + ",");
                resultInfo.Append(result.AnalysisStatus.ToString());

                this.TextWriter.WriteLine(peptideInfo.ToString() + resultInfo.ToString());
            }
        }
        public void TestVerySaturatedPeptide()
        {
            string uimfFileLocation = Cheetah;

            LcImsPeptideSearchParameters parameters = new LcImsPeptideSearchParameters
            {
                ChargeStateMax = 2,
                NetTolerance = 0.03,
                IsotopicFitScoreThreshold = 0.15,
                MassToleranceInPpm = 30,
                NumPointForSmoothing = 9
            };

            string peptide = "NFPSPVDAAFR";
            double net = 0.45;

            PeptideTarget target = new PeptideTarget(1, peptide, net);

            LcImsPeptideSearchWorkfow lcImsPeptideSearchWorkfow = new LcImsPeptideSearchWorkfow(uimfFileLocation, parameters);
            lcImsPeptideSearchWorkfow.RunInformedWorkflow(target);
        }
        public void TestSinglePeptideDidNotFind()
        {
            string uimfFileLocation = Cheetah;
            //string netAlignmentFileLocation = @"..\..\..\testFiles\Sarc_MS2_90_6Apr11_Cheetah_11-02-19_NetAlign.csv";

            //IInterpolation interpolation = AlignmentImporter.ReadFile(netAlignmentFileLocation);

            LcImsPeptideSearchParameters parameters = new LcImsPeptideSearchParameters
            {
                ChargeStateMax = 5,
                NetTolerance = 0.2,
                IsotopicFitScoreThreshold = 0.15,
                MassToleranceInPpm = 30,
                NumPointForSmoothing = 9
            };

            string peptide = "TILDDLRAEDHFSVIDFNQNIR";
            double net = 0.48228999972343445;

            List<Modification> modificationList = new List<Modification>();
            //modificationList.Add(Modification.Oxidation);
            //modificationList.Add(Modification.Carbamidomethylation);
            //modificationList.Add(Modification.Carbamidomethylation);

            PeptideTarget target = new PeptideTarget(1, peptide, net, modificationList);

            LcImsPeptideSearchWorkfow lcImsPeptideSearchWorkfow = new LcImsPeptideSearchWorkfow(uimfFileLocation, parameters, null);
            var correlationResult = lcImsPeptideSearchWorkfow.RunInformedWorkflow(target);

            Console.WriteLine(correlationResult.ReferenceLcImsTargetResult.NormalizedElutionTime);
        }
        public void TestSinglePeptide2()
        {
            string uimfFileLocation = Cheetah;

            LcImsPeptideSearchParameters parameters = new LcImsPeptideSearchParameters
            {
                ChargeStateMax = 5,
                NetTolerance = 0.2,
                IsotopicFitScoreThreshold = 0.15,
                MassToleranceInPpm = 30,
                NumPointForSmoothing = 9
            };

            string peptide = "ATVLNYLPK";
            double net = 0.3612;

            PeptideTarget target = new PeptideTarget(1, peptide, net);
            DriftTimeTarget driftTimeTarget = new DriftTimeTarget("Test Target", 19.62, target, 2);
            target.DriftTimeTargetList.Add(driftTimeTarget);

            LcImsPeptideSearchWorkfow lcImsPeptideSearchWorkfow = new LcImsPeptideSearchWorkfow(uimfFileLocation, parameters);
            ChargeStateCorrelationResult correlationResult = lcImsPeptideSearchWorkfow.RunInformedWorkflow(target);

            using (ImsTargetResultExporter resultsExporter = new ImsTargetResultExporter("outputSingle.csv"))
            {
                if (correlationResult != null) resultsExporter.AppendCorrelationResultToCsv(correlationResult);
            }
        }
        public void TestSinglePeptide()
        {
            string uimfFileLocation = Cheetah;

            LcImsPeptideSearchParameters parameters = new LcImsPeptideSearchParameters
            {
                ChargeStateMax = 5,
                NetTolerance = 0.1,
                IsotopicFitScoreThreshold = 0.15,
                MassToleranceInPpm = 30,
                ScanWindowWidth = 4,
                NumPointForSmoothing = 9
            };

            string peptide = "DGWHSWPIAHQWPQGPSAVDAAFSWEEK";
            double net = 0.4832;

            PeptideTarget target = new PeptideTarget(1, peptide, net);

            LcImsPeptideSearchWorkfow lcImsPeptideSearchWorkfow = new LcImsPeptideSearchWorkfow(uimfFileLocation, parameters);
            lcImsPeptideSearchWorkfow.RunInformedWorkflow(target);
        }
        public void TestInterestingPeptideThatHasOverlappingInterferenceTowardsEndOfElution()
        {
            string uimfFileLocation = @"..\..\..\testFiles\Sarc_MS2_90_6Apr11_Cheetah_11-02-19.uimf";
            string netAlignmentFileLocation = @"..\..\..\testFiles\Sarc_MS2_90_6Apr11_Cheetah_11-02-19_NetAlign.csv";

            IInterpolation interpolation = AlignmentImporter.ReadFile(netAlignmentFileLocation);

            LcImsPeptideSearchParameters parameters = new LcImsPeptideSearchParameters
            {
                ChargeStateMax = 5,
                NetTolerance = 0.03,
                IsotopicFitScoreThreshold = 0.15,
                MassToleranceInPpm = 30,
                NumPointForSmoothing = 9
            };

            string peptide = "LCHCPVGYTGPFCDVDTK";
            double net = 0.3041;

            List<Modification> modificationList = new List<Modification>();
            //modificationList.Add(Modification.Oxidation);
            modificationList.Add(Modification.Carbamidomethylation);
            modificationList.Add(Modification.Carbamidomethylation);
            modificationList.Add(Modification.Carbamidomethylation);

            PeptideTarget target = new PeptideTarget(1, peptide, net, modificationList);

            LcImsPeptideSearchWorkfow lcImsPeptideSearchWorkfow = new LcImsPeptideSearchWorkfow(uimfFileLocation, parameters, interpolation);
            var correlationResult = lcImsPeptideSearchWorkfow.RunInformedWorkflow(target);

            Console.WriteLine(correlationResult.ReferenceLcImsTargetResult.NormalizedElutionTime);
        }
        public void TestDataExtractionSpeedSingleTarget()
        {
            string uimfFileLocation = Cheetah;

            LcImsPeptideSearchParameters parameters = new LcImsPeptideSearchParameters
            {
                ChargeStateMax = 5,
                NetTolerance = 0.1,
                IsotopicFitScoreThreshold = 0.15,
                MassToleranceInPpm = 30,
                NumPointForSmoothing = 9
            };

            string peptide = "QGHNSVFLIKGDK";
            double net = 0.2493;

            PeptideTarget target = new PeptideTarget(1, peptide, net);
            List<PeptideTarget> targetList = new List<PeptideTarget>();
            targetList.Add(target);

            LcImsPeptideSearchWorkfow lcImsPeptideSearchWorkfow = new LcImsPeptideSearchWorkfow(uimfFileLocation, parameters);
            lcImsPeptideSearchWorkfow.ExtractData(targetList);
        }
 public ChargeStateCorrelationResult(PeptideTarget imsTarget, LcImsTargetResult referenceLcImsTargetResult)
 {
     this.ImsTarget = imsTarget;
     this.ReferenceLcImsTargetResult = referenceLcImsTargetResult;
     this.CorrelationMap = new Dictionary<LcImsTargetResult, double>();
 }
        /// <summary>
        /// The run informed workflow.
        /// </summary>
        /// <param name="target">
        /// The Target.
        /// </param>
        /// <returns>
        /// The <see cref="ChargeStateCorrelationResult"/>.
        /// </returns>
        public ChargeStateCorrelationResult RunInformedWorkflow(PeptideTarget target)
        {
            Composition targetComposition = target.CompositionWithoutAdduct;
            double targetMass = targetComposition.Mass;
            string empiricalFormula = targetComposition.ToPlainString();

            double targetNet = target.NormalizedElutionTime;
            double targetNetMin = targetNet - this._parameters.NetTolerance;
            double targetNetMax = targetNet + this._parameters.NetTolerance;

            double reverseAlignedNetMin = targetNetMin;
            double reverseAlignedNetMax = targetNetMax;

            if (this._netAlignment != null)
            {
                double reverseAlignedNet = this.GetReverseAlignedNet(targetNet);
                reverseAlignedNetMin = reverseAlignedNet - this._parameters.NetTolerance;
                reverseAlignedNetMax = reverseAlignedNet + this._parameters.NetTolerance;
            }

            int scanLcSearchMin = (int)Math.Floor(reverseAlignedNetMin * this.NumberOfFrames);
            int scanLcSearchMax = (int)Math.Ceiling(reverseAlignedNetMax * this.NumberOfFrames);

            int iteration = (targetComposition == null) ? 1 : this._parameters.ChargeStateMax;
            for (int chargeState = 1; chargeState <= iteration; chargeState++)
            {
                if (targetComposition != null)
                {
                    Ion targetIon = new Ion(targetComposition, chargeState);
                    target.MassWithAdduct = targetIon.GetMonoIsotopicMz();
                }

                double minMzForSpectrum = target.MassWithAdduct - (1.6 / chargeState);
                double maxMzForSpectrum = target.MassWithAdduct + (4.6 / chargeState);

                // Generate Theoretical Isotopic Profile
                IsotopicProfile theoreticalIsotopicProfile = this._theoreticalFeatureGenerator.GenerateTheorProfile(empiricalFormula, chargeState);
                List<Peak> theoreticalIsotopicProfilePeakList = theoreticalIsotopicProfile.Peaklist.Cast<Peak>().ToList();

                // Find XIC Features
                IEnumerable<FeatureBlob> featureBlobs = this.FindFeatures(target.MassWithAdduct, scanLcSearchMin, scanLcSearchMax);

                // Filter away small XIC peaks
                featureBlobs = FeatureDetection.FilterFeatureList(featureBlobs, 0.25);

                if(!featureBlobs.Any())
                {
                    LcImsTargetResult result = new LcImsTargetResult
                    {
                        ChargeState = chargeState,
                        AnalysisStatus = AnalysisStatus.XicNotFound
                    };

                    target.ResultList.Add(result);
                }

                // Check each XIC Peak found
                foreach (var featureBlob in featureBlobs)
                {
                    // Setup result object
                    LcImsTargetResult result = new LcImsTargetResult
                    {
                        ChargeState = chargeState,
                        AnalysisStatus = AnalysisStatus.Positive
                    };

                    target.ResultList.Add(result);

                    FeatureBlobStatistics statistics = featureBlob.CalculateStatistics();
                    int unsaturatedIsotope = 0;
                    FeatureBlob isotopeFeature = null;

                    int scanLcMin = statistics.ScanLcMin;
                    int scanLcMax = statistics.ScanLcMax;
                    int scanImsMin = statistics.ScanImsMin;
                    int scanImsMax = statistics.ScanImsMax;

                    // TODO: Verify that there are no peaks at isotope #s 0.5 and 1.5?? (If we filter on drift time, this shouldn't actually be necessary)

                    // Find an unsaturated peak in the isotopic profile
                    for (int i = 1; i < 10; i++)
                    {
                        if (!statistics.IsSaturated) break;

                        // Target isotope m/z
                        double isotopeTargetMz = (target.CompositionWithoutAdduct != null) ? new Ion(targetComposition, chargeState).GetIsotopeMz(i) : target.MassWithAdduct;

                        // Find XIC Features
                        IEnumerable<FeatureBlob> newFeatureBlobs = this.FindFeatures(isotopeTargetMz, scanLcMin - 20, scanLcMax + 20);

                        // If no feature, then get out
                        if (!newFeatureBlobs.Any())
                        {
                            statistics = null;
                            break;
                        }

                        bool foundFeature = false;
                        foreach (var newFeatureBlob in newFeatureBlobs.OrderByDescending(x => x.PointList.Count))
                        {
                            var newStatistics = newFeatureBlob.CalculateStatistics();
                            if(newStatistics.ScanImsRep <= scanImsMax && newStatistics.ScanImsRep >= scanImsMin && newStatistics.ScanLcRep <= scanLcMax && newStatistics.ScanLcRep >= scanLcMin)
                            {
                                isotopeFeature = newFeatureBlob;
                                foundFeature = true;
                                break;
                            }
                        }

                        if(!foundFeature)
                        {
                            statistics = null;
                            break;
                        }

                        statistics = isotopeFeature.CalculateStatistics();
                        unsaturatedIsotope = i;
                    }

                    // Bad Feature, so get out
                    if (statistics == null)
                    {
                        result.AnalysisStatus = AnalysisStatus.IsotopicProfileNotFound;
                        continue;
                    }

                    // TODO: Calculate accurate NET and drift time using quadratic equation
                    int scanLcRep = statistics.ScanLcRep + 1;
                    int scanImsRep = statistics.ScanImsRep;

                    // Calculate NET using aligned data if applicable
                    double net = scanLcRep / this.NumberOfFrames;
                    if (this._netAlignment != null)
                    {
                        net = this._netAlignment.Interpolate(net);
                    }

                    FeatureBlob featureToUseForResult = unsaturatedIsotope > 0 ? isotopeFeature : featureBlob;

                    // Set data to result
                    result.FeatureBlobStatistics = statistics;
                    result.IsSaturated = unsaturatedIsotope > 0;
                    result.ScanLcRep = statistics.ScanLcRep;
                    result.NormalizedElutionTime = net;
                    result.DriftTime = this._uimfReader.GetDriftTime(statistics.ScanLcRep, statistics.ScanImsRep, true);
                    result.XicFeature = featureToUseForResult;

                    // Don't consider bogus results
                    if (scanImsRep < 5 || scanImsRep > this.NumberOfScans - 5)
                    {
                        result.AnalysisStatus = AnalysisStatus.DriftTimeError;
                        continue;
                    }

                        // Don't consider bogus results
                        if (scanLcRep < 3 || scanLcRep > this.NumberOfFrames - 4)
                        {
                            result.AnalysisStatus = AnalysisStatus.ElutionTimeError;
                            continue;
                        }

                        // TODO: ViperCompatibleMass Alignment???
                    if (target.TargetType == TargetType.Peptide)
                    {
                        // Filter by NET
                        if (net > targetNetMax || net < targetNetMin)
                        {
                            result.AnalysisStatus = AnalysisStatus.ElutionTimeError;
                            continue;
                        }
                    }

                    //Console.WriteLine(Target.PeptideSequence + "\t" + targetMass + "\t" + targetMz + "\t" + scanLcRep);

                    // Get ViperCompatibleMass Spectrum Data
                    XYData massSpectrum = this.GetMassSpectrum(scanLcRep, scanImsRep, minMzForSpectrum, maxMzForSpectrum);
                    List<Peak> massSpectrumPeakList = this._peakDetector.FindPeaks(massSpectrum);
                    //WriteXYDataToFile(massSpectrum, targetMz);

                    // Find Isotopic Profile
                    List<Peak> massSpectrumPeaks;
                    IsotopicProfile observedIsotopicProfile = this._msFeatureFinder.IterativelyFindMSFeature(massSpectrum, theoreticalIsotopicProfile, out massSpectrumPeaks);

                    // Add data to result
                    result.MassSpectrum = massSpectrum;

                    // No need to move on if the isotopic profile is not found
                    if (observedIsotopicProfile == null || observedIsotopicProfile.MonoIsotopicMass < 1)
                    {
                        result.AnalysisStatus = AnalysisStatus.IsotopicProfileNotFound;
                        continue;
                    }

                    // Add data to result
                    result.IsotopicProfile = observedIsotopicProfile;
                    result.MonoisotopicMass = observedIsotopicProfile.MonoIsotopicMass;
                    result.PpmError = Math.Abs(PeptideUtil.PpmError(targetMass, observedIsotopicProfile.MonoIsotopicMass));

                    // If not enough peaks to reach unsaturated isotope, no need to move on
                    if (observedIsotopicProfile.Peaklist.Count <= unsaturatedIsotope)
                    {
                        result.AnalysisStatus = AnalysisStatus.IsotopicProfileNotFound;
                        continue;
                    }

                    // If the mass error is too high, then ignore
                    if (result.PpmError > this._parameters.MassToleranceInPpm)
                    {
                        result.AnalysisStatus = AnalysisStatus.MassError;
                        continue;
                    }

                    // Correct for Saturation if needed
                    if (unsaturatedIsotope > 0)
                    {
                        IsotopicProfileUtil.AdjustSaturatedIsotopicProfile(observedIsotopicProfile, theoreticalIsotopicProfile, unsaturatedIsotope);
                    }

                    //WriteMSPeakListToFile(observedIsotopicProfile.Peaklist, targetMz);

                    // TODO: This is a hack to fix an issue where the peak width is being calculated way too large which causes the leftOfMonoPeakLooker to use too wide of a tolerance
                    MSPeak monoPeak = observedIsotopicProfile.getMonoPeak();
                    if (monoPeak.Width > 0.15) monoPeak.Width = 0.15f;

                    // Filter out flagged results
                    MSPeak peakToLeft = this._leftOfMonoPeakLooker.LookforPeakToTheLeftOfMonoPeak(monoPeak, observedIsotopicProfile.ChargeState, massSpectrumPeaks);
                    if (peakToLeft != null)
                    {
                        result.AnalysisStatus = AnalysisStatus.PeakToLeft;
                        continue;
                    }

                    double isotopicFitScore;

                    // Calculate isotopic fit score
                    if(unsaturatedIsotope > 0)
                    {
                        int unsaturatedScanLc = this.FindFrameNumberUseForIsotopicProfile(target.MassWithAdduct, scanLcRep, scanImsRep);

                        if (unsaturatedScanLc > 0)
                        {
                            // Use the unsaturated profile if we were able to get one
                            XYData unsaturatedMassSpectrum = this.GetMassSpectrum(unsaturatedScanLc, scanImsRep, minMzForSpectrum, maxMzForSpectrum);
                            //WriteXYDataToFile(unsaturatedMassSpectrum, targetMz);
                            List<Peak> unsaturatedMassSpectrumPeakList = this._peakDetector.FindPeaks(unsaturatedMassSpectrum);
                            isotopicFitScore = this._isotopicPeakFitScoreCalculator.GetFit(theoreticalIsotopicProfilePeakList, unsaturatedMassSpectrumPeakList, 0.15, this._parameters.MassToleranceInPpm);
                        }
                        else
                        {
                            // Use the saturated profile
                            isotopicFitScore = this._isotopicPeakFitScoreCalculator.GetFit(theoreticalIsotopicProfilePeakList, massSpectrumPeakList, 0.15, this._parameters.MassToleranceInPpm);
                        }
                    }
                    else
                    {
                        isotopicFitScore = this._isotopicPeakFitScoreCalculator.GetFit(theoreticalIsotopicProfilePeakList, massSpectrumPeakList, 0.15, this._parameters.MassToleranceInPpm);
                    }

                    // Add data to result
                    result.IsotopicFitScore = isotopicFitScore;

                    // Filter out bad isotopic fit scores
                    if (isotopicFitScore > this._parameters.IsotopicFitScoreThreshold && unsaturatedIsotope == 0)
                    {
                        result.AnalysisStatus = AnalysisStatus.IsotopicFitScoreError;
                        continue;
                    }

                    Console.WriteLine(chargeState + "\t" + unsaturatedIsotope + "\t" + statistics.ScanLcMin + "\t" + statistics.ScanLcMax + "\t" + statistics.ScanLcRep + "\t" + statistics.ScanImsMin + "\t" + statistics.ScanImsMax + "\t" + statistics.ScanImsRep + "\t" + isotopicFitScore.ToString("0.0000") + "\t" + result.NormalizedElutionTime.ToString("0.0000") + "\t" + result.DriftTime.ToString("0.0000"));
                }

                // TODO: Isotope Correlation (probably not going to do because of saturation issues)
            }

            // Charge State Correlation (use first unsaturated XIC feature)
            List<ChargeStateCorrelationResult> chargeStateCorrelationResultList = new List<ChargeStateCorrelationResult>();
            ChargeStateCorrelationResult bestCorrelationResult = null;
            double bestCorrelationSum = -1;

            List<LcImsTargetResult> resultList = target.ResultList.Where(x => x.AnalysisStatus == AnalysisStatus.Positive).OrderBy(x => x.IsotopicFitScore).ToList();
            int numResults = resultList.Count;

            for (int i = 0; i < numResults; i++)
            {
                LcImsTargetResult referenceResult = resultList[i];

                ChargeStateCorrelationResult chargeStateCorrelationResult = new ChargeStateCorrelationResult(target, referenceResult);
                chargeStateCorrelationResultList.Add(chargeStateCorrelationResult);

                for (int j = i + 1; j < numResults; j++)
                {
                    LcImsTargetResult testResult = resultList[j];
                    double correlation = FeatureCorrelator.CorrelateFeaturesUsingLc(referenceResult.XicFeature, testResult.XicFeature);
                    chargeStateCorrelationResult.CorrelationMap.Add(testResult, correlation);
                    Console.WriteLine(referenceResult.FeatureBlobStatistics.ScanLcRep + "\t" + referenceResult.FeatureBlobStatistics.ScanImsRep + "\t" + testResult.FeatureBlobStatistics.ScanLcRep + "\t" + testResult.FeatureBlobStatistics.ScanImsRep + "\t" + correlation);
                }

                List<LcImsTargetResult> possibleBestResultList;
                double correlationSum = chargeStateCorrelationResult.GetBestCorrelation(out possibleBestResultList);

                if(correlationSum > bestCorrelationSum)
                {
                    bestCorrelationSum = correlationSum;
                    bestCorrelationResult = chargeStateCorrelationResult;
                }
            }

            // TODO: Score Target

            // TODO: Quantify Target (return isotopic profile abundance)

            return bestCorrelationResult;
        }
 public bool Equals(PeptideTarget other)
 {
     return MoleculeUtil.AreCompositionsEqual(this.CompositionWithAdduct, other.CompositionWithAdduct) &&
         this.NormalizedElutionTime == other.NormalizedElutionTime &&
         this.TargetDescriptor == other.TargetDescriptor &&
         this.PeptideSequence == other.PeptideSequence;
 }
        public static List<PeptideTarget> ImportMassTags(string serverName, string databaseName, double maxMsgfSpecProb = 1e-10, bool isForCalibration = false)
        {
            List<PeptideTarget> targetList = new List<PeptideTarget>();

            // Build connection string
            string connectionString = BuildConnectionString(serverName, databaseName);

            // Using connection
            var dbFactory = DbProviderFactories.GetFactory("System.Data.SqlClient");
            using (var connection = dbFactory.CreateConnection())
            {
                connection.ConnectionString = connectionString;
                connection.Open();

                // Execute query
                string queryString = isForCalibration ? GetQueryForCalibration() : GetQuery();
                using (DbCommand command = connection.CreateCommand())
                {
                    command.CommandText = queryString;
                    command.CommandTimeout = 120;
                    DbDataReader reader = command.ExecuteReader();

                    PeptideTarget currentImsTarget = null;

                    while (reader.Read())
                    {
                        int massTagId = Convert.ToInt32(reader["Mass_Tag_ID"]);
                        string peptide = Convert.ToString(reader["peptide"]);
                        double normalizedElutionTime = Convert.ToDouble(reader["Avg_GANET"]);
                        int modCount = Convert.ToInt16(reader["Mod_Count"]);

                        List<Modification> modificationList = new List<Modification>();

                        if(modCount > 0)
                        {
                            string modificationString = Convert.ToString(reader["Mod_Description"]);
                            string[] splitModString = modificationString.Split(',');
                            foreach (var singleModString in splitModString)
                            {
                                string modificationName = singleModString.Split(':')[0];
                                Modification modification = _dmsModToInformedModMap[modificationName];
                                modificationList.Add(modification);
                            }
                        }

                        bool isSameTarget = IsSameTarget(currentImsTarget, peptide, normalizedElutionTime, modificationList);

                        if(!isSameTarget)
                        {
                            currentImsTarget = new PeptideTarget(massTagId, peptide, normalizedElutionTime, modificationList);
                            targetList.Add(currentImsTarget);
                        }

                        int chargeState = Convert.ToInt16(reader["Conformer_Charge"]);
                        double driftTime = Convert.ToDouble(reader["Drift_Time_Avg"]);

                        DriftTimeTarget driftTimeTarget = new DriftTimeTarget(massTagId.ToString(CultureInfo.InvariantCulture), driftTime, currentImsTarget.EmpiricalFormula, new IonizationAdduct(chargeState));
                        currentImsTarget.DriftTimeTargetList.Add(driftTimeTarget);
                    }
                }
            }

            return targetList;
        }
        public static bool IsSameTarget(PeptideTarget currentImsTarget, string peptide, double normalizedElutionTime, List<Modification> modificationList)
        {
            int modCount = modificationList.Count;

            if (currentImsTarget != null)
            {
                if (currentImsTarget.PeptideSequence == peptide && Math.Abs(currentImsTarget.NormalizedElutionTime - normalizedElutionTime) < 0.00001)
                {
                    if (modCount == currentImsTarget.ModificationList.Count)
                    {
                        if (modCount == 0) return true;
                        else
                        {
                            if (currentImsTarget.ModificationList[0] == modificationList[0]) return true;
                        }
                    }
                }
            }

            return false;
        }