protected void WritePeak(StreamWriter writer, PeakList <T> pl)
        {
            PeakList <T> pkl;

            //Mascot Generic Format 要求每个spectrum不能超过10000个离子。
            if (pl.Count > 10000)
            {
                pkl = new PeakList <T>(pl);
                pkl.SortByIntensity();
                pkl.RemoveRange(10000, pkl.Count - 10000);
                pkl.SortByMz();
            }
            else
            {
                pkl = pl;
            }

            //if (pkl.Any(m => m.Charge > 0))
            //{
            //  foreach (T peak in pkl)
            //  {
            //    writer.WriteLine(MyConvert.Format("{0:0.#####} {1:0.0} {2}", peak.Mz, peak.Intensity, peak.Charge));
            //  }
            //}
            //else
            //{
            foreach (T peak in pkl)
            {
                writer.WriteLine(MyConvert.Format("{0:0.#####} {1:0.0###}", peak.Mz, peak.Intensity));
            }
            //}

            writer.WriteLine(MascotGenericFormatConstants.END_PEAK_LIST_TAG);
            writer.WriteLine();
        }
        public PeakList <T> Process(PeakList <T> t)
        {
            if (!t.Any(m => m.Charge > 0))
            {
                return(t);
            }

            Parallel.ForEach(t, m =>
            {
                if (m.Charge > 1)
                {
                    m.Mz     = m.Mz * m.Charge - Atom.H.MonoMass * (m.Charge - 1);
                    m.Charge = 1;
                }
            });

            var peaks = (from p in t
                         where p.Charge == 1
                         orderby p.Intensity
                         select p).ToList();

            var deleted = new HashSet <T>();

            while (peaks.Count > 0)
            {
                var mz          = peaks[0].Mz;
                var mzTolerance = PrecursorUtils.ppm2mz(mz, ppmTolerance);
                var minMz       = mz - mzTolerance;
                var maxMz       = mz + mzTolerance;
                var curPeaks    = (from p in peaks
                                   where p.Mz >= minMz && p.Mz <= maxMz
                                   select p).ToList();
                if (curPeaks.Count > 1)
                {
                    var nIntensity = curPeaks.Sum(m => m.Intensity);
                    var nMz        = curPeaks.Sum(m => m.Mz * m.Intensity) / nIntensity;
                    peaks[0].Mz        = nMz;
                    peaks[0].Intensity = nIntensity;
                    curPeaks.Remove(peaks[0]);
                    deleted.UnionWith(curPeaks);
                }
                peaks.RemoveAll(m => curPeaks.Contains(m));
            }

            t.RemoveAll(m => deleted.Contains(m));

            t.SortByMz();
            return(t);
        }
        public void AddPeaks(int minMz, int maxMz, int scan, PeakList <Peak> pkl)
        {
            this.MinMz = minMz;

            this.MaxMz = maxMz;

            List <Peak> peaks = new List <Peak>();

            for (int i = 0; i <= maxMz; i++)
            {
                peaks.Add(new Peak(0.0, 0.0));
            }

            pkl.SortByMz();

            foreach (var p in pkl)
            {
                var mz = (int)Math.Round(p.Mz);
                if (mz < minMz)
                {
                    continue;
                }

                if (mz > maxMz)
                {
                    break;
                }

                peaks[mz] = p;
            }

            for (int i = minMz; i <= maxMz; i++)
            {
                string peak = i.ToString();
                this[peak, scan] = new PeakItem(scan, peaks[i].Mz, peaks[i].Intensity);
            }
        }
        public PeakList <T> Process(PeakList <T> t)
        {
            t.SortByMz();

            //删除固定区间。
            var index = 0;

            while (index < t.Count)
            {
                var peak = t[index];

                if (peak.Mz > options.MaxFixIonMz)
                {
                    break;
                }

                double mass;
                if (peak.Charge > 1)
                {
                    mass = PrecursorUtils.MzToMH(peak.Mz, peak.Charge, true);
                    if (mass > options.MaxFixIonMz)
                    {
                        index++;
                        continue;
                    }
                }
                else
                {
                    mass = peak.Mz;
                }

                bool bRemoved = false;
                for (int i = 0; i < options.FixIonRanges.Count; i++)
                {
                    var ion = options.FixIonRanges[i];

                    if (mass < ion.First)
                    {
                        break;
                    }

                    if (mass > ion.Second)
                    {
                        continue;
                    }

                    bRemoved = true;
                    t.RemoveAt(index);
                    break;
                }

                if (!bRemoved)
                {
                    index++;
                }
            }

            var precursorMass = PrecursorUtils.MzToMH(t.PrecursorMZ, t.PrecursorCharge, true);

            if (options.RemoveHighRange)
            {
                var maxPeak = precursorMass - options.Protease.GetHighBYFreeWindow() - options.MzTolerance;
                if (options.RemovePrecusor)
                {
                    t.RemoveAll(peak =>
                    {
                        double mass = PrecursorUtils.MzToMH(peak.Mz, peak.Charge, true);
                        return(mass >= maxPeak);
                    });
                }
                else
                {
                    var precursorLess  = precursorMass - options.MzTolerance;
                    var precursorLarge = precursorMass + options.MzTolerance;
                    t.RemoveAll(peak =>
                    {
                        double mass = PrecursorUtils.MzToMH(peak.Mz, peak.Charge, true);
                        return((mass >= maxPeak && mass <= precursorLess) || mass > precursorLarge);
                    });
                }
            }

            if (options.RemovePrecursorMinusLabel)
            {
                var ionmass    = precursorMass - options.LabelMass;
                var minIonMass = ionmass - options.MzTolerance;
                var maxIonMass = ionmass + options.MzTolerance;
                t.RemoveAll(peak =>
                {
                    double mass = PrecursorUtils.MzToMH(peak.Mz, peak.Charge, true);
                    return(mass >= minIonMass && mass <= maxIonMass);
                });
            }

            return(t);
        }