public FdrResult FilterByFdr(double maxFdr)
        {
            if (this.Count == 0)
            {
                return(new FdrResult());
            }

            this.ForEach(m => m.FilterByFdr(maxFdr));

            if (OverlapBySearchEngine.Count == 0)
            {
                return(new FdrResult()
                {
                    Fdr = maxFdr, Spectra = this.GetUnconflictedOptimalSpectra()
                });
            }

            double nextFdr = maxFdr;

            while (true)
            {
                FdrResult result = DoCalculateOverlappedPeptideFdr(nextFdr);
                if (result.Fdr <= maxFdr)
                {
                    return(result);
                }
                nextFdr = nextFdr - FalseDiscoveryRateUtils.CalculateStepFdr(nextFdr);
                this.ForEach(m => m.FilterByFdr(nextFdr));
            }
        }
        private FdrResult DoCalculateOverlappedPeptideFdr(double individualFdr)
        {
            FdrResult result = new FdrResult();

            List <IIdentifiedSpectrum> spectra = new List <IIdentifiedSpectrum>();

            int decoyCount  = 0;
            int targetCount = 0;

            foreach (var dsList in OverlapBySearchEngine)
            {
                List <IIdentifiedSpectrum> peps = dsList.GetUnconflictedOptimalSpectra();

                //根据实验文件名分类。这样可以降低需要比较的集合大小。
                var expGroups = peps.GroupBy(m => m.Query.FileScan.Experimental);

                foreach (var group in expGroups)
                {
                    //根据scan分类。
                    var spGroup = group.GroupBy(m => m.Query.FileScan.FirstScan);
                    foreach (var sp in spGroup)
                    {
                        var lst = sp.ToList();
                        if (lst.Count > 1 && IsEngineConflict(lst))
                        {
                            result.ConflictSpectra.AddRange(lst);

                            var spectrum = conflictFunc.Process(lst);
                            lst.Clear();
                            if (spectrum != null)
                            {
                                lst.AddRange(spectrum);
                            }
                        }

                        if (lst.Count >= dsOptions.Options.MinimumEngineAgreeCount)
                        {
                            spectra.AddRange(lst);
                            if (lst[0].FromDecoy)
                            {
                                decoyCount++;
                            }
                            else
                            {
                                targetCount++;
                            }
                        }
                    }
                }
            }

            if (dsOptions.Options.MinimumEngineAgreeCount <= 1)
            {
                var noOverlapSpectra = NoOverlaps.GetOptimalSpectra();
                foreach (var s in noOverlapSpectra)
                {
                    if (s.FromDecoy)
                    {
                        decoyCount++;
                    }
                    else
                    {
                        targetCount++;
                    }
                }
                spectra.AddRange(noOverlapSpectra);
            }

            result.Spectra = spectra;
            result.Fdr     = fdrCalc.Calculate(decoyCount, targetCount);

            return(result);
        }