<commit_before>﻿using MassSpectrometry;
using OldInternalLogic;
using Proteomics;
using Spectra;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;

namespace InternalLogicEngineLayer
{
    public class AnalysisEngine : MyEngine
    {

        #region Private Fields

        private const double binTol = 0.003;
        private const double comboThresholdMultiplier = 3;
        private const int max_mods_for_peptide = 3;
        private readonly int maximumMissedCleavages;
        private readonly int maxModIsoforms;
        private readonly ParentSpectrumMatch[][] newPsms;
        private readonly List<Protein> proteinList;
        private readonly List<MorpheusModification> variableModifications;
        private readonly List<MorpheusModification> fixedModifications;
        private readonly List<MorpheusModification> localizeableModifications;
        private readonly Protease protease;
        private readonly List<SearchMode> searchModes;
        private readonly IMsDataFile<IMzSpectrum<MzPeak>> myMsDataFile;
        private readonly Tolerance fragmentTolerance;
        private readonly Action<BinTreeStructure, string> action1;
        private readonly Action<List<NewPsmWithFDR>, string> action2;
        private readonly Action<List<ProteinGroup>, string> action3;
        private readonly bool doParsimony;
        private Dictionary<CompactPeptide, HashSet<PeptideWithSetModifications>> compactPeptideToProteinPeptideMatching;

        #endregion Private Fields

        #region Public Constructors

        public AnalysisEngine(ParentSpectrumMatch[][] newPsms, Dictionary<CompactPeptide, HashSet<PeptideWithSetModifications>> compactPeptideToProteinPeptideMatching, List<Protein> proteinList, List<MorpheusModification> variableModifications, List<MorpheusModification> fixedModifications, List<MorpheusModification> localizeableModifications, Protease protease, List<SearchMode> searchModes, IMsDataFile<IMzSpectrum<MzPeak>> myMsDataFile, Tolerance fragmentTolerance, Action<BinTreeStructure, string> action1, Action<List<NewPsmWithFDR>, string> action2, Action<List<ProteinGroup>, string> action3, bool doParsimony, int maximumMissedCleavages, int maxModIsoforms) : base(2)
        {
            this.doParsimony = doParsimony;
            this.newPsms = newPsms;
            this.compactPeptideToProteinPeptideMatching = compactPeptideToProteinPeptideMatching;
            this.proteinList = proteinList;
            this.variableModifications = variableModifications;
            this.fixedModifications = fixedModifications;
            this.localizeableModifications = localizeableModifications;
            this.protease = protease;
            this.searchModes = searchModes;
            this.myMsDataFile = myMsDataFile;
            this.fragmentTolerance = fragmentTolerance;
            this.action1 = action1;
            this.action2 = action2;
            this.action3 = action3;
            this.maximumMissedCleavages = maximumMissedCleavages;
            this.maxModIsoforms = maxModIsoforms;
        }

        #endregion Public Constructors

        #region Public Methods

        public static Dictionary<CompactPeptide, PeptideWithSetModifications> GetSingleMatchDictionary(Dictionary<CompactPeptide, HashSet<PeptideWithSetModifications>> fullSequenceToProteinPeptideMatching)
        {
            // Right now very stupid, add the first decoy one, and if no decoy, add the first one
            var outDict = new Dictionary<CompactPeptide, PeptideWithSetModifications>();
            foreach (var kvp in fullSequenceToProteinPeptideMatching)
            {
                var k = kvp.Key;
                var val = kvp.Value;
                bool sawDecoy = false;
                foreach (var entry in val)
                {
                    if (entry.protein.isDecoy)
                    {
                        outDict[kvp.Key] = entry;
                        sawDecoy = true;
                        break;
                    }
                }
                if (sawDecoy == false)
                    outDict[kvp.Key] = kvp.Value.First();
            }

            return outDict;
        }

        public Dictionary<CompactPeptide, HashSet<PeptideWithSetModifications>> ApplyProteinParsimony(Dictionary<CompactPeptide, HashSet<PeptideWithSetModifications>> fullSequenceToProteinPeptideMatching, out HashSet<CompactPeptide> uniquePeptides)
        {
            // TODO**: protein group may have a shared peptide that is only shared within the group (peptide is unique to the group but shared within the group)
            // TODO**: how to handle indistinguishable proteins?
            // TODO**: rewrite parsimony function using protein group objects (more efficient)
            // TODO**: add proteins with unique peptides first, makes algo faster, use parsimony on remainder
            // TODO**: how to handle multiple CompactPeptide objects that have the same basesequence (should be treated as 1 unaccounted-for
            //         peptide, not 10 for example)

            uniquePeptides = new HashSet<CompactPeptide>();

            // finds unique peptides first (not really used for parsimony but used later for protein groups)
            // unique peptide is a peptide that can belong to only one protein
            foreach (var kvp in fullSequenceToProteinPeptideMatching)
            {
                List<Protein> proteinList = new List<Protein>();

                foreach (var peptide in kvp.Value)
                {
                    if (!proteinList.Contains(peptide.protein))
                    {
                        proteinList.Add(peptide.protein);
                    }
                }

                if (proteinList.Count == 1)
                {
                    uniquePeptides.Add(kvp.Key);
                }
            }

            // makes dictionary with proteins as keys and list of associated peptides as the value
            Dictionary<Protein, HashSet<CompactPeptide>> newDict = new Dictionary<Protein, HashSet<CompactPeptide>>();

            foreach (var kvp in fullSequenceToProteinPeptideMatching)
            {
                foreach (var virtualPeptide in kvp.Value)
                {
                    // find peptides associated with new protein
                    if (!newDict.ContainsKey(virtualPeptide.protein))
                    {
                        HashSet<CompactPeptide> peptides = new HashSet<CompactPeptide>();

                        foreach (var kvp1 in fullSequenceToProteinPeptideMatching)<commit_msg>protein group update (peptides only belong to decoy proteins if shared between target/decoy proteins)<commit_after>﻿using MassSpectrometry;
using OldInternalLogic;
using Proteomics;
using Spectra;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;

namespace InternalLogicEngineLayer
{
    public class AnalysisEngine : MyEngine
    {

        #region Private Fields

        private const double binTol = 0.003;
        private const double comboThresholdMultiplier = 3;
        private const int max_mods_for_peptide = 3;
        private readonly int maximumMissedCleavages;
        private readonly int maxModIsoforms;
        private readonly ParentSpectrumMatch[][] newPsms;
        private readonly List<Protein> proteinList;
        private readonly List<MorpheusModification> variableModifications;
        private readonly List<MorpheusModification> fixedModifications;
        private readonly List<MorpheusModification> localizeableModifications;
        private readonly Protease protease;
        private readonly List<SearchMode> searchModes;
        private readonly IMsDataFile<IMzSpectrum<MzPeak>> myMsDataFile;
        private readonly Tolerance fragmentTolerance;
        private readonly Action<BinTreeStructure, string> action1;
        private readonly Action<List<NewPsmWithFDR>, string> action2;
        private readonly Action<List<ProteinGroup>, string> action3;
        private readonly bool doParsimony;
        private Dictionary<CompactPeptide, HashSet<PeptideWithSetModifications>> compactPeptideToProteinPeptideMatching;

        #endregion Private Fields

        #region Public Constructors

        public AnalysisEngine(ParentSpectrumMatch[][] newPsms, Dictionary<CompactPeptide, HashSet<PeptideWithSetModifications>> compactPeptideToProteinPeptideMatching, List<Protein> proteinList, List<MorpheusModification> variableModifications, List<MorpheusModification> fixedModifications, List<MorpheusModification> localizeableModifications, Protease protease, List<SearchMode> searchModes, IMsDataFile<IMzSpectrum<MzPeak>> myMsDataFile, Tolerance fragmentTolerance, Action<BinTreeStructure, string> action1, Action<List<NewPsmWithFDR>, string> action2, Action<List<ProteinGroup>, string> action3, bool doParsimony, int maximumMissedCleavages, int maxModIsoforms) : base(2)
        {
            this.doParsimony = doParsimony;
            this.newPsms = newPsms;
            this.compactPeptideToProteinPeptideMatching = compactPeptideToProteinPeptideMatching;
            this.proteinList = proteinList;
            this.variableModifications = variableModifications;
            this.fixedModifications = fixedModifications;
            this.localizeableModifications = localizeableModifications;
            this.protease = protease;
            this.searchModes = searchModes;
            this.myMsDataFile = myMsDataFile;
            this.fragmentTolerance = fragmentTolerance;
            this.action1 = action1;
            this.action2 = action2;
            this.action3 = action3;
            this.maximumMissedCleavages = maximumMissedCleavages;
            this.maxModIsoforms = maxModIsoforms;
        }

        #endregion Public Constructors

        #region Public Methods

        public static Dictionary<CompactPeptide, PeptideWithSetModifications> GetSingleMatchDictionary(Dictionary<CompactPeptide, HashSet<PeptideWithSetModifications>> fullSequenceToProteinPeptideMatching)
        {
            // Right now very stupid, add the first decoy one, and if no decoy, add the first one
            var outDict = new Dictionary<CompactPeptide, PeptideWithSetModifications>();
            foreach (var kvp in fullSequenceToProteinPeptideMatching)
            {
                var k = kvp.Key;
                var val = kvp.Value;
                bool sawDecoy = false;
                foreach (var entry in val)
                {
                    if (entry.protein.isDecoy)
                    {
                        outDict[kvp.Key] = entry;
                        sawDecoy = true;
                        break;
                    }
                }
                if (sawDecoy == false)
                    outDict[kvp.Key] = kvp.Value.First();
            }

            return outDict;
        }

        public Dictionary<CompactPeptide, HashSet<PeptideWithSetModifications>> ApplyProteinParsimony(Dictionary<CompactPeptide, HashSet<PeptideWithSetModifications>> fullSequenceToProteinPeptideMatching, out HashSet<CompactPeptide> uniquePeptides)
        {
            // TODO**: protein group may have a shared peptide that is only shared within the group (peptide is unique to the group but shared within the group)
            // TODO**: how to handle indistinguishable proteins?
            // TODO**: rewrite parsimony function using protein group objects (more efficient)
            // TODO**: add proteins with unique peptides first, makes algo faster, use parsimony on remainder
            // TODO**: how to handle multiple CompactPeptide objects that have the same basesequence (should be treated as 1 unaccounted-for
            //         peptide, not 10 for example)
            // TODO**: if a peptide is shared between target and decoy proteins, remove its association with the target proteins, leave 
            //         only the decoy proteins

            foreach(var kvp in fullSequenceToProteinPeptideMatching)
            {
                bool psmContainsDecoyProtein = false;

                foreach(var peptide in kvp.Value)
                {
                    if(peptide.protein.isDecoy)
                    {
                        psmContainsDecoyProtein = true;
                    }
                }

                // if psm contains decoy protein, remove all target proteins associated with the psm
                if(psmContainsDecoyProtein)
                {
                    HashSet<PeptideWithSetModifications> peptidesToRemove = new HashSet<PeptideWithSetModifications>();

                    foreach (var peptide in kvp.Value)
                    {
                        if(!peptide.protein.isDecoy)
                        {
                            peptidesToRemove.Add(peptide);
                        }
                    }

                    foreach(var peptide in peptidesToRemove)
                    {
                        kvp.Value.Remove(peptide);
                    }
                }
            }

            // finds unique peptides first (not really used for parsimony but used later for protein groups)
            // unique peptide is a peptide that can belong to only one protein
            uniquePeptides = new HashSet<CompactPeptide>();
            foreach (var kvp in fullSequenceToProteinPeptideMatching)
            {
                List<Protein> proteinList = new List<Protein>();

                foreach (var peptide in kvp.Value)
                {
                    if (!proteinList.Contains(peptide.protein))
                    {
                        proteinList.Add(peptide.protein);
                    }
                }

                if (proteinList.Count == 1)
                {
                    uniquePeptides.Add(kvp.Key);
                }
            }

            // makes dictionary with proteins as keys and list of associated peptides as the value
            Dictionary<Protein, HashSet<CompactPeptide>> newDict = new Dictionary<Protein, HashSet<CompactPeptide>>();

            foreach (var kvp in fullSequenceToProteinPeptideMatching)
            {
                foreach (var virtualPeptide in kvp.Value)
                {
                    // find peptides associated with new protein
                    if (!newDict.ContainsKey(virtualPeptide.protein))
                    {
                        HashSet<CompactPeptide> peptides = new HashSet<CompactPeptide>();

                        foreach (var kvp1 in fullSequenceToProteinPeptideMatching)
{'fraction_non_alphanumeric': 0.06118014531133292, 'fraction_numerical': 0.003259319617029945, 'mean_word_length': 2.236923076923077, 'pattern_counts': {'":': 0, '<': 97, '<?xml version=': 0, '>': 97, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3493541', 'n_tokens_mistral': 3890, 'n_tokens_neox': 3429, 'n_words': 961}