Source code for MSQuant: PILpeptides.cs, MSQlib1/src/massspec/PILpeptides.cs.

Table of contents page.

Home page for MSQuant.

//****************************************************************************
//* Copyright (C) 2006 Peter Mortensen and Matthias Mann                     *
//* This file is part of MSQuant.                                            *
//*                                                                          *
//* MSQuant is distributed under the terms of                                *
//* the GNU General Public License. See src/COPYING.TXT or                   *
//* <http://www.gnu.org/licenses/gpl.txt> for details.                       *
//*                                                                          *
//* MSQuant is free software; you can redistribute it                        *
//* and/or modify it under the terms of the GNU                              *
//* General Public License as published by the Free                          *
//* Software Foundation; either version 2 of the                             *
//* License, or (at your option) any later version.                          *
//*                                                                          *
//* MSQuant is distributed in the hope that it will be                       *
//* useful, but WITHOUT ANY WARRANTY; without even the                       *
//* implied warranty of MERCHANTABILITY or FITNESS FOR                       *
//* A PARTICULAR PURPOSE.  See the GNU General Public                        *
//* License for more details.                                                *
//*                                                                          *
//* You should have received a copy of the GNU General                       *
//* Public License along with MSQuant; if not, write to                      *
//* the Free Software Foundation, Inc., 59 Temple                            *
//* Place, Suite 330, Boston, MA  02111-1307  USA                            *
//*                                                                          *
//* Purpose: encapsulation of a list of peptides. E.g. no                    *
//*          direct indexing so we can apply filters, do                     *
//*          caching, change representation, do sorting by                   *
//*          sorting keys, lazy sort, parallel structures for                *
//*          caching information such that PeptideHitStructure               *
//*          does not need to have so many fields, etc.                      *
//*                                                                          *
//*          Note: some redundancy here as purpose is                        *
//*            repeated in header for Class PILpeptides (but                 *
//*            the justification is that it is far down in the               *
//*            file...).                                                     *
//*                                                                          *
//****************************************************************************

//****************************************************************************
//*                               CEBI                                       *
//*                    Software Development Group                            *
//*                         Peter Mortensen                                  *
//*                E-mail: NUKESPAMMERSdrmortensen@get2netZZZZZZ.dk          *
//*                 WWW: http://www.cebi.sdu.dk/                             *
//*                                                                          *
//*  Program for post-processing of result from search in mass               *
//*    spectrometric data.                                                   *
//*                                                                          *
//*    FILENAME:   PILpeptides.cs                                            *
//*    TYPE:  VISUAL_BASIC                                                   *
//*                                                                          *
//* CREATED: PM 2008-10-30   Vrs 1.0. Translated from VB.NET,                *
//                           file PILpeptides.vb, 2006-03-15                 *
//* UPDATED: PM 2008-xx-xx                                                   *
//*                                                                          *
//****************************************************************************

//Future:
//  1. Some filter for the "verified" field. Such that client don't have to
//     check it.
//
//  2. Let this class handle things that are now in MascotResultParser.vb,
//     sum score (scoreInABC), counts in .
//     Perhaps extend/rename peptideCount() to return all these values (?).


using System.Text; //For StringBuilder
using System.Collections.Generic; //For Dictionary. And List.
using System.Diagnostics; //For Trace. And its Assert.


//Changed PM_FAST_SERIALISATION 2006-12-15
using System.Runtime.Serialization;
//For SerializationInfo and StreamingContext.

//Changed PM_FAST_SERIALISATION 2006-12-15
using SimmoTech.Utils.Serialization;
//For SerializationWriter


//using utilityStatic; //For numbersClose    Not possible to use for classes in C#...

//using MolecularSharedStructures;


//****************************************************************************
//d$ <summary>
//d$   Purpose: Namespace for lower layers of mass spectrometric
//d$            applications: raw data file handling, descriptive statistics,
//d$            fragment masses, digestion, file associations, etc.
//d$   <see cref="T:VBXMLDoc.CVBXMLDoc" />.
//d$   <isUnitTest></isUnitTest>
//d$   <applicationname>test_rawDataFileHandling</applicationname>
//d$   <author>Peter Mortensen</author>
//d$   <seealso>http://www.cebi.sdu.dk/</seealso>
//d$   <codetype>PLATFORM independent</codetype>
//d$ </summary>
namespace massSpectrometryBase
{

    //Should client specify a list of keys instead?
    public enum peptideSortOrderEnum
    {
        enumSequenceThenScore = 313
        //Asc and descending, respectively.
    } //peptideSortOrderEnum


    //Changed PM_SILACDISH_UNIQUELY_HIGHEST_SCORING 2008-10-02
    //Various option if
    public struct highestScoringParametersStructure
    {
        public bool differentCharge;
        public bool differentRawFile;

        public bool differentModificationSet;
        public bool differentModificationCounts2;

        //Changed PM_SILAC_AWARE_PEPTIDEFILTERDIALOG 2008-10-08
        //List of modifications to exclude for use in ,
        //differentModificationSet typically the SILAC modifications (for
        //the current quantitation mode).
        //Nothing means that the exclude filer is not in effect.
        public Dictionary<int, int> differentModification_excludedMods2;
        //Note: not a simple list. This is to comply with how this
        //      is done in the rest of the program... The value is
        //      the modification count, but we don't use it here.

        public bool differentSILACdish;


        //Utility function. Shouls it be here?
        public static List<int> hash2list(Dictionary<int, int> anInHash)
        {
            List<int> toReturn = null;

            if (anInHash != null)
            {
                toReturn = new List<int>();
                Dictionary<int, int>.Enumerator hashEnumerator2 =
                    anInHash.GetEnumerator();
                while (hashEnumerator2.MoveNext())
                {
                    int curKey = hashEnumerator2.Current.Key;
                    int curValue = hashEnumerator2.Current.Value;

                    toReturn.Add(curKey);
                } //Hash iteration.
            }
            else
            {
                int peter2 = 2;
            }
            return toReturn;
        } //hash2list()


        public static Dictionary<int, int> list2hash(List<int> anInList)
        {

            Dictionary<int, int> toReturn = null;
            if (anInList != null)
            {
                toReturn = new Dictionary<int, int>();

                //int someModID = 0;
                foreach (int someModID in anInList)
                {
                    toReturn.Add(someModID, 1);
                } //Through anInList
            }
            else
            {
                int peter2 = 2;
            }

            return toReturn;
        } //list2hash()


    } //highestScoringParametersStructure


    // [Serializable()]
    public struct peptideFilterStructure //: ISerializable
    {
        //Changed PM_SAVEMB4_QUESTIONS 2008-06-30
        //Why do we save this structure to the MB3/MB4 file??? Will it
        //save some temporary filters for exporting??. Is it
        //because we physically parse in more peptides than is shown?
        //
        //Answer: we ***don't*** save all (only the first 5 fields...) and
        //        we just set the lists and hashes to Nothing/null
        //        when the MB3/MB4 file is read.
        //
        //But the question remains: why do we do this at all? Effectively 
        //we may not - it is because the filters in the client(s) are 
        //overwritten from the outside and it does not matter what is
        //read in?


        //Note: if fields are added readFromStream2() and
        //      addToStream2() should be updated!!!

        //Changed PM_FAST_SERIALISATION 2006-12-15

        public int chargeMin; //Inclusive
        public int chargeMax; //Inclusive

        public int seqLengthMin; //Inclusive
        public int seqLengthMax; //Inclusive

        public double massMin; //Inclusive
        public double massMax; //Inclusive


        //Changed PM_SILACDISH_UNIQUELY_HIGHEST_SCORING 2008-10-02. Replaced
        //  with something slightly different!
        //Dim highestScoringUniquelyModified As Boolean
        public bool onlyHighestScoring;

        public highestScoringParametersStructure highestScoringParameters;

        //Changed PM_EXCLUDE_MODFILTER 2008-06-30
        //'Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-24. Moved to here.
        //Dim pepModFilter3 As List(Of Integer)
        public List<int> pepIncludeModFilter3;

        public List<int> pepExcludeModFilter;
        //Changed PM_MARKER_FOR_MB4 2008-06-30. -for pepExcludeModFilter. Do
        //  we need/do we actually save this?


        //Helper field - for easy/fast lookup. Derived
        //from field peptideModificationFilter2.
        public Dictionary<int, int> includeModHash_INTERNAL2;

        //Changed PM_EXCLUDE_MODFILTER 2008-06-30
        public Dictionary<int, int> excludeModHash_INTERNAL;

        //Changed PM_HIGHESTSCORINGUNIQUELYMODIFIED_BUG 2007-10-05. Now
        //  per iterator.
        public Dictionary<string, int> exHash2_INTERNAL;

        //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-25
        public double scoreMin; //Inclusive
        public double scoreMax2; //Inclusive

        public bool verifiedOnly;
        public bool quantifiedOnly;

        //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27
        //Some tag the client can use, e.g. to
        public int tag1; //  mark as permanent filter - depends on the
        //  iterator constructor used.

        //Some tag the client can use, e.g. marked for
        public int tag2; //deletion or no filter.

        //Changed PM_MASSACC_PEPFILTER 2007-09-05
        //Inclusive. Relative; unit [ppm]
        public double massAccuracyMin;
        //Inclusive. Relative; unit [ppm]
        public double massAccuracyMax;

        //Changed PM_RAWFILE_PEPFILTER 2007-11-16
        //Negative value is taken as meaning no filter.
        public int rawFileID;


        //Changed PM_FAST_SERIALISATION_READ 2007-01-01
        //****************************************************************************
        //*    For peptideFilterSpecificationStructure.                              *
        //****************************************************************************
        public static peptideFilterStructure readFromStream2(
            ref SerializationReader anInReader, int aMBfileVersion)
        {
            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-29. To get
            //  proper defaults. Otherwise e.g. the score range would
            //  be empty, [0; 0].
            //Dim toReturn As peptideFilterSpecificationStructure
            peptideFilterStructure toReturn =
                peptideFilterStructure.noPepFilter();

            toReturn.chargeMin = anInReader.ReadInt32();

            int chargeMax = anInReader.ReadInt32();
            Trace.Assert(
                chargeMax >= 0 && chargeMax <= 29,
                "PIL ASSERT. Deserialisation, chargeMax is out of range." +
                chargeMax + ".");
            toReturn.chargeMax = chargeMax;

            toReturn.seqLengthMin = anInReader.ReadInt32();
            toReturn.seqLengthMax = anInReader.ReadInt32();

            //Changed PM_SILACDISH_UNIQUELY_HIGHEST_SCORING 2008-10-02.
            //  Equivalent. But why do we store the peptide filter as all?
            //  See comments in the beginning of this structure...
            //toReturn.highestScoringUniquelyModified = anInReader.ReadBoolean()
            toReturn.onlyHighestScoring = anInReader.ReadBoolean();

            {
                //Changed PM_REFACTOR 2008-10-30. Generated by VB to C#
                //converted. Disable it for now to stay faithful to
                //the original.
                //highestScoringParametersStructure hsPars = default(highestScoringParametersStructure);
                highestScoringParametersStructure hsPars;

                //For notational convenience.

                hsPars.differentCharge = false;
                hsPars.differentRawFile = false;
                hsPars.differentModificationSet = true;
                hsPars.differentModificationCounts2 = true;

                //Changed PM_SILAC_AWARE_PEPTIDEFILTERDIALOG 2008-10-08
                hsPars.differentModification_excludedMods2 = null;

                hsPars.differentSILACdish = false;

                toReturn.highestScoringParameters = hsPars;
            } //Block.

            toReturn.pepIncludeModFilter3 = null;

            //Changed PM_EXCLUDE_MODFILTER 2008-06-30
            toReturn.pepExcludeModFilter = null;

            return toReturn;
        } //readFromStream2(). For peptideFilterStructure.


        //Changed PM_FAST_SERIALISATION_AVOID_DOTNET 2006-12-19
        //****************************************************************************
        //*    For peptideFilterSpecificationStructure.                                        *
        //****************************************************************************
        public void addToStream2(
          ref SerializationWriter anInOutWriter, int aMBfileVersion)
        {
            //aVersion: e.g. 300 for MB3, 400 for MB4.
            //SERMARK13. A marker. Keep it.

            anInOutWriter.Write(chargeMin);
            anInOutWriter.Write(chargeMax);
            anInOutWriter.Write(seqLengthMin);
            anInOutWriter.Write(seqLengthMax);

            //Changed PM_SILACDISH_UNIQUELY_HIGHEST_SCORING 2008-10-02
            //anInOutWriter.Write(highestScoringUniquelyModified)
            anInOutWriter.Write(onlyHighestScoring);
        } //addToStream2(). For peptideFilterStructure.


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public static List<int> deepCopyModList(ref List<int> anInModList)
        {
            List<int> toReturn = null;
            if (anInModList != null)
            {
                int inLen = anInModList.Count;
                Trace.Assert(
                    inLen > 0,
                    "PIL ASSERT. Mod list is empty (but not Nothing).");

                toReturn = new List<int>();

                //int modID = 0;
                foreach (int modID in anInModList)
                {
                    toReturn.Add(modID);
                }
            }
            else
            {
                //If input is Nothing then we also return Nothing.
                int peter2 = 2;
            }
            return toReturn;
        } //deepCopyModList()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public peptideFilterStructure deepCopy2()
        {

            peptideFilterStructure toReturn = this;
            toReturn.includeModHash_INTERNAL2 = null;

            //Changed PM_EXCLUDE_MODFILTER 2008-06-30
            toReturn.excludeModHash_INTERNAL = null;

            //Changed PM_HIGHESTSCORINGUNIQUELYMODIFIED_BUG 2007-10-05
            toReturn.exHash2_INTERNAL = null;

            //Changed PM_EXCLUDE_MODFILTER 2008-06-30
            //toReturn.pepModFilter3 = _
            //  peptideFilterStructure.deepCopyModList(Me.pepModFilter3)
            toReturn.pepIncludeModFilter3 =
                peptideFilterStructure.deepCopyModList(
                    ref this.pepIncludeModFilter3);
            toReturn.pepExcludeModFilter =
                peptideFilterStructure.deepCopyModList(
                    ref this.pepExcludeModFilter);

            return toReturn;
        } //deepCopy2()


        //Changed PM_REFACTOR 2007-08-27. From defaultOptions().
        //  It also needed from QuantWindow.vb.
        //
        //Should this be a constructor instead?
        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public static peptideFilterStructure noPepFilter()
        {
            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-24
            //.peptideFilterSpecification.chargeMin = 1
            //.peptideFilterSpecification.chargeMax = 20
            //.peptideFilterSpecification.seqLengthMin = 1
            //.peptideFilterSpecification.seqLengthMax = 99
            //.peptideFilterSpecification.highestScoringUniquelyModified = _
            //  False

            //Changed PM_REFACTOR 2008-10-30. Generated by VB to C#
            //converted. Disable it for now to stay faithful to
            //the original.
            //peptideFilterStructure somePeptideFilter =
            //    default(peptideFilterStructure);
            //peptideFilterStructure somePeptideFilter;
            peptideFilterStructure somePeptideFilter =
              default(peptideFilterStructure); //Use it after all.

            somePeptideFilter.chargeMin = 1;
            somePeptideFilter.chargeMax = 20;

            somePeptideFilter.seqLengthMin = 1;
            somePeptideFilter.seqLengthMax = 99;

            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-28
            somePeptideFilter.massMin = 0.0;
            somePeptideFilter.massMax = 8888.0;

            //Changed PM_SILACDISH_UNIQUELY_HIGHEST_SCORING 2008-10-02
            //somePeptideFilter.highestScoringUniquelyModified = False
            somePeptideFilter.onlyHighestScoring = false;

            //Changed PM_REFACTOR 2008-10-30. Generated by VB to C#
            //converted. Disable it for now to stay faithful to
            //the original.
            //highestScoringParametersStructure pars =
            //  default(highestScoringParametersStructure);
            highestScoringParametersStructure pars;

            pars.differentCharge = false;
            pars.differentRawFile = false;
            pars.differentModificationSet = true;

            pars.differentModificationCounts2 = true;
            //Count was actually considered in the old...

            pars.differentModification_excludedMods2 = null;
            pars.differentSILACdish = false;
            somePeptideFilter.highestScoringParameters = pars;


            //Changed PM_EXCLUDE_MODFILTER 2008-06-30
            //'Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-29
            //'somePeptideFilter.peptideModificationFilter2 = _
            //'  New List(Of Integer) 'Empty, but existing...
            //somePeptideFilter.pepModFilter3 = Nothing
            somePeptideFilter.pepIncludeModFilter3 = null;
            somePeptideFilter.pepExcludeModFilter = null;

            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-29
            somePeptideFilter.includeModHash_INTERNAL2 = null; //Just in case.

            //Changed PM_EXCLUDE_MODFILTER 2008-06-30
            somePeptideFilter.excludeModHash_INTERNAL = null; //Just in case.

            //Changed PM_HIGHESTSCORINGUNIQUELYMODIFIED_BUG 2007-10-05
            somePeptideFilter.exHash2_INTERNAL = null; //Just in case.

            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-25
            somePeptideFilter.scoreMin = 1;
            somePeptideFilter.scoreMax2 = 200.0;

            //Changed PM_MASSACC_PEPFILTER 2007-09-05
            somePeptideFilter.massAccuracyMin = -99999.0;
            somePeptideFilter.massAccuracyMax = 99999.0;

            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27
            somePeptideFilter.tag1 = 0;
            //No permanent filter, at least not yet.
            somePeptideFilter.tag2 = PILpeptides.NOFILTER_CODE2;

            //Changed PM_RAWFILE_PEPFILTER 2007-11-16
            somePeptideFilter.rawFileID = -10000;
            //No filter; all...

            return somePeptideFilter;
        } //noFilter()


        //Changed PM_REFACTOR 2007-08-29
        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public static Dictionary<int, int> hashForModFilter(
            List<int> anInModList)
        {

            Dictionary<int, int> toReturn = new Dictionary<int, int>();

            if (anInModList != null)
            {
                //int modID = 0;
                foreach (int modID in anInModList)
                {
                    toReturn.Add(modID, 1);
                }
            }
            else
            {
                //Input was Nothing. We return an empty hash. That is fine.
                int peter2 = 2;
            }

            return toReturn;
        } //hashForModFilter()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public static bool anyModsInFilter(
            List<modificationCountStruct> anInModsInPeptide,
            Dictionary<int, int> anInLookupHash)
        {
            bool toReturn = true;

            Trace.Assert(
                (anInLookupHash != null),
                "PIL ASSERT. anInLookupHash Is Nothing....");

            //Changed PM_REFACTOR 2006-10-22
            //Dim mods As ArrayList = pept.modHits
            List<modificationCountStruct> mods2 = anInModsInPeptide;

            bool anyModsInPeptide = (mods2 != null) && mods2.Count > 0;
            //Note: relies on short-circuit
            //  boolean logic - this order must be preserved!
            if (anyModsInPeptide)
            {
                int lastIndex = mods2.Count - 1;
                int j = 0;
                bool matchedID = false;
                for (j = 0; j <= lastIndex; j++)
                {
                    modificationCountStruct curMod = mods2[j];
                    if (anInLookupHash.ContainsKey(curMod.quantModificationID))
                    {
                        matchedID = true;
                        break; // TODO: might not be correct. Was : Exit For
                    }
                }
                if (!matchedID)
                {
                    toReturn = false;
                }
                else
                {
                    int peter8 = 8;
                }
            }
            else
            {
                //No modifications for peptide. As we have a filter then
                //the peptide must be excluded....
                toReturn = false;
            } //Any mods (in peptide).

            return toReturn;
        } //anyModsInFilter()
    } //peptideFilterSpecificationStructure()


    //****************************************************************************
    //*  CLASS NAME:   peptideListIterator                                       *
    //d$ <summary>
    //d$   Purpose: syntactic sugar to ease clients use of PILpeptides
    //d$
    //d$
    //d$
    //d$   <see cref="T:VBXMLDoc.CVBXMLDoc" />.
    //d$   <applicationname>xyz</applicationname>
    //d$   <author>Peter Mortensen</author>
    //d$   <seealso>http://www.cebi.sdu.dk/</seealso>
    //d$   <codetype>PLATFORM independent</codetype>
    //d$ </summary>
    public class peptideListIterator
    {
        PILpeptides mPeptideList;

        //Makes more than one iterator at a time possible.
        int mIteratorToken;

        //Zero-based. Used for a service for the client.
        int mIndex;

        //May not be needed.
        //'Using this will result in more copies. Perhaps PILpeptides should
        //'handle this?
        //Dim mCurrentPeptide As PeptideHitStructure


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //*                                                                          *
        //*    Note: uses whatever peptide filter is already set in                  *
        //*          the peptide list (if any).                                      *
        //*                                                                          *
        //****************************************************************************
        public peptideListIterator(PILpeptides aPeptideList)
        {
            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27
            peptideFilterStructure filter = peptideFilterStructure.noPepFilter();

            //Using this constructor means the ***permanent*** filter will be
            //used (that was set previously - could even have been set during a
            //previous session of this program (saved with MB3))

            filter.tag1 = PILpeptides.MARK_PERMANENT_FILTER2;
            //The permanent filter
            //  may or may not have been set (by call
            //  to setPermanentPeptideFilter()). If it has not
            //  been set then it defaults to no filter.
            //
            //In any case all other fields of 'filter' will be ignored. We only
            //use tag1 to signal to the other class that some already stored filter
            //in the peptide list (in that other class) should be used.

            this.init(ref aPeptideList, filter);
        } //Constructor. One of two.


        //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-26
        //****************************************************************************
        //*    <placeholder for header>                                              *
        //*    Constructor for letting the client specify a per-iterator peptide     *
        //*    filter, e.g. exporting peptides based on a user defined               *
        //*    peptide filter.                                                       *
        //*                                                                          *
        //****************************************************************************
        public peptideListIterator(
            PILpeptides aPeptideList, peptideFilterStructure aFilter)
        {

            //Using this constructor means some ***user supplied*** filter will
            //be used. E.g. at export time.

            //Changed PM_PEPTIDECOUNT_BUG 2007-09-04
            aFilter.tag1 = 0;
            //Meaning: not permanent.

            //If Not aFilter.pepModFilter3 Is Nothing Then
            //    aFilter.tag2 = 0 'Clears "no filter"
            //End If
            aFilter.tag2 = 0;
            //Clears "no filter"

            this.init(ref aPeptideList, aFilter);
        } //Constructor. One of two.


        //Changed PM_REFACTOR 2007-08-26. To be shared by the two
        //  constructor, one of which is new of this date.
        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        private void init(
            ref PILpeptides aPeptideList, peptideFilterStructure aFilter)
        {

            Trace.Assert(
                (aPeptideList != null), "PIL ASSERT. aPeptideList is Nothing...");

            mPeptideList = aPeptideList;
            mIteratorToken = mPeptideList.newIteratorToken(aFilter);
            mIndex = -1;

            //mCurrentPeptide.queryNumber = -1

            mPeptideList.resetRead(mIteratorToken);
        } //init()


        //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27
        //Used only for serialisation?
        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public int getIterToken()
        {

            return mIteratorToken;
        } //getIterToken()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public bool nextPeptide(out PeptideHitStructure aOutPeptide)
        {
            mIndex += 1;
            int someIteratorToken = 0;
            bool toReturn =
                mPeptideList.nextPeptide(
                    mIteratorToken, out aOutPeptide, out someIteratorToken);
            //mCurrentPeptide = aOutPeptide

            if (toReturn == true)
            {
                //Later: tell mPeptideList to get rid of the iterator.
                int peter1 = 1;
            }

            return toReturn;
        } //nextPeptide()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public bool nextPeptide(
            out PeptideHitStructure aOutPeptide, out int anOutPeptideToken)
        {
            mIndex += 1;
            bool toReturn =
                mPeptideList.nextPeptide(
                    mIteratorToken, out aOutPeptide, out anOutPeptideToken);
            //mCurrentPeptide = aOutPeptide

            if (toReturn == true)
            {
                //Later: tell mPeptideList to get rid of the iterator.
                int peter1 = 1;
            }

            return toReturn;
        } //nextPeptide()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public void currentPeptide(ref PeptideHitStructure aOutPeptide)
        {
            //What if we are past the collection? Or not started yet?

            //Trace.Assert(mCurrentPeptide.queryNumber >= 0, _
            //  "PIL ASSERT. Current peptide is undefined.")

            //aOutPeptide = mCurrentPeptide
            mPeptideList.currentPeptide(mIteratorToken, out aOutPeptide);
        } //currentPeptide()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public void updateCurrentPeptide(PeptideHitStructure anInPeptide)
        {
            //What if we are past the collection? Or not started yet?

            //Trace.Assert(mCurrentPeptide.queryNumber >= 0, _
            //  "PIL ASSERT. Current peptide is undefined.")

            //aOutPeptide = mCurrentPeptide
            mPeptideList.updateCurrentPeptide(mIteratorToken, anInPeptide);
        } //updateCurrentPeptide()


    } //class peptideListIterator


    //****************************************************************************
    //*  CLASS NAME:   PILpeptides                                               *
    //d$ <summary>
    //d$   Purpose: encapsulation of a list of peptides. E.g. no direct indexing
    //d$            so we can apply filters, do caching, change representation,
    //d$            do sorting by sorting keys, lazy sort, parallel structures
    //d$            for caching information such that PeptideHitStructure does
    //d$            not need to have so many fields, etc.
    //d$
    //d$   <see cref="T:VBXMLDoc.CVBXMLDoc" />.
    //d$   <applicationname>xyz</applicationname>
    //d$   <author>Peter Mortensen</author>
    //d$   <seealso>http://www.cebi.sdu.dk/</seealso>
    //d$   <codetype>PLATFORM independent</codetype>
    //d$ </summary>
    //[Serializable()]
    public class PILpeptides //: ISerializable
    {
        //Note: if fields are added readFromStream2() and
        //      addToStream2() should be updated!!!

        //Changed PM_FAST_SERIALISATION 2006-12-15

        //Changed PM_MASCOTSCORE_ASDOUBLE 2008-11-25
        ////Note: Integer for now. Follows PeptideHitStructure/MascotScore
        //public const int FIXED_SCORE_FOR_INSERTED_PEPTIDES = 99;
        public const double FIXED_SCORE_FOR_INSERTED_PEPTIDES2 = 99.0;

        //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27
        public const int MARK_PERMANENT_FILTER2 = -359;

        //Changed PM_ZAP_PEPTIDES 2006-10-25
        public const int NOFILTER_CODE2 = -1;
        public const int MARKEDFORDELETION_CODE2 = -2;

        //Not yet...
        //Private Structure peptideDerivedFieldsStructure
        //    Dim includedInFilter As Boolean 'Note: this is for the base filter. Other
        //    'filters may be applied on top, but this is somewhere else as there
        //    'may be many filters at the same time. Perhaps that should be placed
        //    'in peptideListIterator?
        //End Structure 'peptideDerivedFieldsStructure

        //[Serializable()]
        private struct iteratorStructure
        {
            //No ID needed. Only known of admin of a list of these.

            public int readIndex;
            public int lastReadIndex;

            //A convenient place to
            public peptideSortOrderEnum sortOrder;
            //  store this information.

            //Also a convenient place..
            public int lastIndex;

            //Reference to some
            public List<int> sortedKeys2;
            //  sorted keys.

            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27
            public peptideFilterStructure filter;

            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-28
            //Now per-iterator
            public int effectiveNumberOfPeptides;
            //  count.
        } //iteratorStructure


        //Changed PM_REFACTOR 2006-11-08. Not used...
        // 'Used with mExcludeHash
        // Private Structure reducedPeptide1Structure2
        //     'No ID needed. Only known of admin of a list of these
        //
        //     Dim readIndex As Integer
        //     Dim lastReadIndex As Integer
        //
        //     Dim sortOrder As peptideSortOrderEnum 'A convenient place to
        //     '  store this information.
        //
        //     Dim lastIndex As Integer 'Also a convenient place..
        //
        //     Dim xxxsortedKeys As ArrayList 'Reference to some sorted keys.
        //
        //     'Future:
        //     '  1. Filters
        // End Structure 'reducedPeptide1Structure


        //****************************************************************************
        //*  CLASS NAME:   SortBySequenceThenScore_usingIndex                        *
        //d$ <summary> N/A. ...
        //d$      Note: xyz                    </summary>
        private class SortBySequenceThenScore_usingIndex :
          System.Collections.Generic.IComparer<int>
        {
            //Changed PM_TYPESAFE 2006-10-25
            //Dim mPeptideList As ArrayList
            List<PeptideHitStructure> mPeptideList3;

            //For debugging/statistics/performance evaluation only.
            int mCompareCalls; 
            int mNonEqualCompareCalls; 


            //****************************************************************************
            //*    <placeholder for header>                                              *
            //****************************************************************************
            public SortBySequenceThenScore_usingIndex(
                List<PeptideHitStructure> aPeptideList)
            {
                //Type of aPeptideList is PeptideHitStructure.

                mPeptideList3 = aPeptideList;
                mCompareCalls = 0;
                mNonEqualCompareCalls = 0;
            } //Constructor.


            //****************************************************************************
            //*    <placeholder for header>                                              *
            //****************************************************************************
            public int Compare(int aItem1, int aItem2)
            {
                int toReturn = 0; //Default: equal.

                mCompareCalls += 1;

                //We can save some just comparing the indexes. But why are
                //we called this way??? The caller should know the two items
                //are equal, at least for integer.
                if (aItem1 != aItem2)
                {
                    PeptideHitStructure pept1 = mPeptideList3[aItem1];
                    PeptideHitStructure pept2 = mPeptideList3[aItem2];

                    mNonEqualCompareCalls += 1;

                    //Changed PM_REFACTOR 2008-10-31
                    //if (pept1.AASequence < pept2.AASequence)
                    //{
                    //    toReturn = -1;
                    //}
                    //else
                    //{
                    //    if (pept1.AASequence > pept2.AASequence)
                    //    {
                    //        toReturn = 1;
                    //    }
                    //    else
                    //    {
                    //          <>
                    //    }
                    //}

                    //Use a culture insensitive option to CompareTo() to speed things
                    //up?
                    //Or is it only for String.Compare()? Does not seem to exist...
                    //
                    //Ref:
                    //  <http://stackoverflow.com/questions/44288/differences-in-string-compare-methods-in-c>
                    int compareResult =
                      pept1.AASequence.CompareTo(pept2.AASequence);

                    if (compareResult != 0)
                    {
                        toReturn = compareResult; //Ascending sort for sequence.
                    }
                    else
                    {
                        //Same sequence, use second key: charge
                        if (pept1.charge < pept2.charge)
                        {
                            toReturn = -1;
                        }
                        else
                        {
                            if (pept1.charge > pept2.charge)
                            {
                                toReturn = 1;
                            }
                            else
                            {
                                //Third key, score, to accomodate entering of the highest
                                //  scoring peptides into the Quantiation window.
                                //
                                //Note 1: descending sort
                                //Note 2: the inserted peptides, currently score 99, are
                                //        considered to have the lowest score.

                                double scoreTol = 0.1;
                                double lowScore = 0.01;

                                //Changed PM_MASCOTSCORE_ASDOUBLE 2008-11-25. No
                                //longer implicit conversion from integer to
                                //double...
                                double effectiveScore1 = pept1.MascotScore2;

                                if (utilityStatic.numbersClose(
                                      effectiveScore1,
                                      FIXED_SCORE_FOR_INSERTED_PEPTIDES2,
                                      scoreTol))
                                {

                                    effectiveScore1 = lowScore;
                                }

                                //Changed PM_MASCOTSCORE_ASDOUBLE 2008-11-25. No
                                //longer implicit conversion from integer to
                                //double...
                                double effectiveScore2 = pept2.MascotScore2;

                                if (utilityStatic.numbersClose(
                                        effectiveScore2,
                                        FIXED_SCORE_FOR_INSERTED_PEPTIDES2,
                                        scoreTol))
                                {

                                    effectiveScore2 = lowScore;
                                }

                                if (effectiveScore1 < effectiveScore2)
                                {
                                    toReturn = 1;
                                    //Note: descending sort
                                }
                                else
                                {
                                    //Changed PM_SORTBUG 2006-03-17
                                    //If effectiveScore1 < effectiveScore2 Then
                                    if (effectiveScore1 > effectiveScore2)
                                    {
                                        toReturn = -1;
                                        //Note: descending sort
                                    }
                                    else
                                    {
                                        //Fourth key: mass
                                        if (pept1.MascotCalculatedMass < pept2.MascotCalculatedMass)
                                        {
                                            toReturn = -1;
                                        }
                                        else
                                        {
                                            if (pept1.MascotCalculatedMass > pept2.MascotCalculatedMass)
                                            {
                                                toReturn = 1;
                                            }
                                            else
                                            {
                                                //Also exacly same mass, use fifth key. This will
                                                //happen for inserted peptides.
                                                if (pept1.rawFileID < pept2.rawFileID)
                                                {
                                                    toReturn = -1;
                                                }
                                                else
                                                {
                                                    if (pept1.rawFileID > pept2.rawFileID)
                                                    {
                                                        toReturn = 1;
                                                    }
                                                    else
                                                    {
                                                        //Sixth key: to have a defined sort order for
                                                        //           double entries (duplication of data
                                                        //           for a spectrum, in the Mascot input file.)
                                                        if (pept1.queryNumber < pept2.queryNumber)
                                                        {
                                                            toReturn = -1;
                                                        }
                                                        else
                                                        {
                                                            if (pept1.queryNumber > pept2.queryNumber)
                                                            {
                                                                toReturn = 1;
                                                            }
                                                            else
                                                            {
                                                                //All 6 keys equal....
                                                                int peter9 = 9;
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        } //Same sequence, use second key: charge

                    } //Sequence compare


                    // 'Note: ascending sort
                    // If pept1.AASequence < pept2.AASequence Then
                    //     toReturn = -1
                    // Else
                    //     If pept1.AASequence > pept2.AASequence Then
                    //         toReturn = 1
                    //     Else
                    //         'Equal primary keys.... Use secondary key
                    //         Dim peter9 As Integer = 9
                    //
                    //         'Note: descending sort
                    //         If pept1.MascotScore < pept2.MascotScore Then
                    //             toReturn = 1
                    //         Else
                    //             If pept1.MascotScore > pept2.MascotScore Then
                    //                 toReturn = -1
                    //             Else
                    //                 'Equal....
                    //                 Dim peter10 As Integer = 10
                    //             End If
                    //         End If
                    //     End If
                    // End If
                }
                else
                {
                    int peter2 = 2; //Indexes equal.
                }

                return toReturn;
            } //Compare()
        } //SortBySequenceThenScore_usingIndex()


        //This is what we are protecting!
        //'Changed PM_TYPESAFE 2006-10-25
        //Dim mPeptides As ArrayList 'Item type is PeptideHitStructure
        private List<PeptideHitStructure> mPeptides2;

        //Note: this
        private int mEffectiveNumberOfPeptides;
        //  is only for the permanent filter.


        //Not yet....
        //'Parallel structure to PeptideHitStructure.
        //Dim mDerivedPeptideFieldsList As ArrayList 'Item type
        //' is : peptideDerivedFieldsStructure

        private peptideSortOrderEnum mSortDefaultOrder;

        private int mIteratorTokenGeneration;
        private int mPeptideTokenBase;

        //Changed PM_TYPESAFE 2006-11-08
        //Dim mIteratorInfo As Hashtable '(iteratorID, interatorInfo)
        //Key: iteratorID
        private Dictionary<int, iteratorStructure> mIteratorInfo2;

        //For caching lists of sorted keys.
        private Dictionary<peptideSortOrderEnum, List<int>> mSortedKeysSet2;

        private peptideFilterStructure mPermanentFilter2;

        //Changed PM_HIGHESTSCORINGUNIQUELYMODIFIED_BUG 2007-10-05. Now
        //  per iterator.
        //'Changed PM_TYPESAFE 2006-11-09
        // ''Changed PM_PEPTIDEFILTER_HIGHESTSCORING 2006-05-19
        //'Dim mExcludeHash As Hashtable 'Related to
        // ''  field highestScoringUniquelyModified in mPermanentFilter.
        //Private mExcludeHash2 As Dictionary(Of String, Integer)

        //Changed PM_HIGHESTSCORINGUNIQUELYMODIFIED_BUG 2007-10-05
        //Used when building
        bool mBuildingExcludeHash;
        //  a data structure when highestScoringUniquelyModified is
        //  in effect.


        //Changed PM_MEMORY_EFFICIENCY 2007-02-19
        private int mEstimatedCapacity;


        //****************************************************************************
        //*    Constructor for PILpeptides                                           *
        //****************************************************************************
        public PILpeptides(int anAnticipatedMaximumNumberOfPeptides)
        {
            //Changed PM_MEMORY_EFFICIENCY 2007-02-19
            mEstimatedCapacity = anAnticipatedMaximumNumberOfPeptides;

            mIteratorTokenGeneration = 311;
            mPeptideTokenBase = 1993;

            mPeptides2 = null; //Lazy instantiation
            mIteratorInfo2 = null; //Lazy instantiation
            mSortedKeysSet2 = null; //Lazy instantiation

            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27. Probably OK to
            //set the single field, but we want isolate it...
            // 'Changed PM_ZAP_PEPTIDES 2006-10-25
            // 'mPermanentFilter.chargeMin = -1 'Flag for no filter
            // mPermanentFilter.chargeMin = NOFILTER_CODE 'Flag for no filter
            //
            // mPermanentFilter.highestScoringUniquelyModified = False 'Default
            // '  is no filter.
            mPermanentFilter2 = peptideFilterStructure.noPepFilter();

            //Changed PM_HIGHESTSCORINGUNIQUELYMODIFIED_BUG 2007-10-05
            //'Changed PM_PEPTIDEFILTER_HIGHESTSCORING 2006-05-19
            //mExcludeHash2 = Nothing 'Lazy instantiation

            mEffectiveNumberOfPeptides = -1;
            //Flag for undefined

            mBuildingExcludeHash = false;

            //Changed PM_ASSERT_ZAPPED_PROTEINS 2006-03-23
            mSortDefaultOrder = peptideSortOrderEnum.enumSequenceThenScore;

            //Changed PM_COMBINED_INDEXOUTOFRANGE_EXCEPTION 2006-03-27
            this.peptidelistChanged();
        } //Constructor. For PILpeptides.


        //Changed PM_FAST_SERIALISATION 2006-12-30
        //****************************************************************************
        //*    For PILpeptides.                                                      *
        //****************************************************************************
        public static PILpeptides readFromStream2(
          ref SerializationReader anInReader, int aMBfileVersion)
        {
            PILpeptides toReturn = new PILpeptides(0);

            //Changed PM_FAST_SERIALISATION_READ 2007-01-01
            //List
            {
                int items = anInReader.ReadOptimizedInt32();
                toReturn.mPeptides2 = new List<PeptideHitStructure>(items);

                int lastIndex = items - 1;
                int j = 0;
                for (j = 0; j <= lastIndex; j++)
                {
                    toReturn.mPeptides2.Add(
                      PeptideHitStructure.readFromStream2(
                        ref anInReader, aMBfileVersion));
                }
            } //Block. Reading list.

            toReturn.mEffectiveNumberOfPeptides = anInReader.ReadInt32();

            toReturn.mSortDefaultOrder =
                (peptideSortOrderEnum)anInReader.ReadInt32();

            toReturn.mIteratorTokenGeneration = anInReader.ReadInt32();
            toReturn.mPeptideTokenBase = anInReader.ReadInt32();

            toReturn.mPermanentFilter2 =
              peptideFilterStructure.readFromStream2(
                ref anInReader, aMBfileVersion);

            return toReturn;
        } //readFromStream2(). For PILpeptides.


        //Changed PM_FAST_SERIALISATION_AVOID_DOTNET 2006-12-19
        //****************************************************************************
        //*    For PILpeptides.                                                      *
        //****************************************************************************
        public void addToStream2(
          ref SerializationWriter anInOutWriter, int aMBfileVersion)
        {
            //aVersion: e.g. 300 for MB3, 400 for MB4.
            //SERMARK14. A marker. Keep it.

            //Not needed anymore.
            //'Changed PM_FAST_SERIALISATION 2006-12-18
            //Me.purgeHiddenPeptides()

            //Changed PM_FAST_SERIALISATION 2006-12-19. Avoid invoking
            //  the .NET serialisation (BinaryFormatter).
            //writer.Write(mPeptides2) 'List(Of PeptideHitStructure)
            //
            //Note: we use the public interface even though we have access to
            //the datastructure. In this way we get rid of the peptides marked
            //for deletion. Those outside the current filter will not be
            //saved either (is that what we want).
            {
                int physicalSize = mPeptides2.Count;

                peptideListIterator pepIter = new peptideListIterator(this);

                //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27
                int token = pepIter.getIterToken();

                //Note: size depends on which filter is applied. In this case
                //      we use the permanent filter (created by the first type
                //      of constructor used above).
                int logicalSize = peptideCount2(token);
                //This may still create a lot of memory garbage - by the
                //current implementation.

                //This is our own encoding.
                anInOutWriter.WriteOptimized(logicalSize);

                int count = 0;

                //Changed PM_REFACTOR_OUT_IS_YOUR_FRIEND 2008-10-30
                //PeptideHitStructure pept =
                //    PeptideHitStructure.blankPeptide(); //Keep compiler happy.
                PeptideHitStructure pept;

                while (!pepIter.nextPeptide(out pept))
                {
                    pept.addToStream2(ref anInOutWriter, aMBfileVersion);
                    count += 1;
                }
                Trace.Assert(
                  logicalSize == count, 
                  "PIL ASSERT. logicalSize ( " + logicalSize + 
                  ") is not the same as count (" + count + ").");

                int purged = physicalSize - logicalSize;

                //For breakpoints.
                if (purged >= 1)
                {
                    int peter1 = 1;
                }
                if (purged >= 2)
                {
                    int peter2 = 2;
                }
                if (purged >= 3)
                {
                    int peter3 = 3;
                }
                if (purged >= 4)
                {
                    int peter4 = 4;
                }
            } //Block.

            //Do we need to store all of these??? E.g. there will
            //be iterator structures active when we start.
            anInOutWriter.Write(mEffectiveNumberOfPeptides);

            //Changed PM_REFACTOR_MARKER 2008-10-30. Is 4-byte integer 
            //the right cast? Yes, the old read (VB version) above was 32 bit.
            anInOutWriter.Write((int)mSortDefaultOrder);

            anInOutWriter.Write(mIteratorTokenGeneration);
            anInOutWriter.Write(mPeptideTokenBase);
            //writer.Write(mIteratorInfo2)  left out.
            //writer.Write(mSortedKeysSet2) left out, created on demand.

            //Changed PM_FAST_SERIALISATION_AVOID_DOTNET 2006-12-19. Call
            //serialisation directly.
            //'writer.Write(mPermanentFilter) 'peptideFilterSpecificationStructure
            //anInOutWriter.WriteObject(mPermanentFilter) 'Is this the right
            //'  way. Should there not be a function for Structures???
            mPermanentFilter2.addToStream2(ref anInOutWriter, aMBfileVersion);

            //writer.Write(mExcludeHash2)  left out. Created on demand.
        } //addToStream2(). For PILpeptides.


        //Changed PM_FAST_SERIALISATION 2006-12-18
        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        private void purgeHiddenPeptides()
        {
            //We may not need this function after all; the elimination is now
            //done on the client side in serialisation.
            Trace.Assert(
              false, "Stop!", 
              "PIL ASSERT. Internal/development assert for stopping execution......");

            //For now: use the public interface. This may create a lot of
            //memory garbage. But we must somehow physically delete the entries
            //as the serialisation run on a Generics list, without any control
            //of which elements are serialised ().
            //
            //In order to prevent unnecessary operations it would also be
            //nice if we could check if it is already done. We could use a flag;
            //will aldo need to be updated if the condition is invalidated, e.g.
            //a peptide.

            int physicalSize = mPeptides2.Count;

            peptideListIterator pepIter = new peptideListIterator(this);
            int token = pepIter.getIterToken();

            int logicalSize = peptideCount2(token);
            //This may still create
            //  a lot of memory garbage - by current implementation.

            if (physicalSize > logicalSize)
            {
                List<PeptideHitStructure> newPeptideList = 
                  new List<PeptideHitStructure>();

                //Changed PM_REFACTOR_OUT_IS_YOUR_FRIEND 2008-10-30
                //PeptideHitStructure pept = PeptideHitStructure.blankPeptide();
                PeptideHitStructure pept;

                //Keep compiler happy.
                while (!pepIter.nextPeptide(out pept))
                {
                    newPeptideList.Add(pept);
                }

                int oldSize = physicalSize;
                int newSize = newPeptideList.Count;
                int purged = oldSize - newSize;

                mPeptides2 = null;
                //Just to be clear we are getting rid of the old
                //  list.
                mPeptides2 = newPeptideList;

                this.peptidelistChanged();
                //Existing sorted keys are invalidated as
            }
            //  some items were deleted.
            else
            {
                int peter2 = 2;
                //No items to leave out.
            }
        } //purgeHiddenPeptides()


        //Changed PM_COMBINED_INDEXOUTOFRANGE_EXCEPTION 2006-03-27
        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public void peptidelistChanged()
        {
            mEffectiveNumberOfPeptides = -1;
            //Flag for undefined
            mSortedKeysSet2 = null;
            //Sort order must be found again (for the
            //  new list)/lazy instantiation.

            mIteratorInfo2 = null;
            //The list is invalidated so we might as
            //  well get rid of any tokens.

            if (mSortedKeysSet2 != null)
            {
                int peter2 = 2;
            }

            if (mIteratorInfo2 != null)
            {
                int peter3 = 3;
            }
        } //peptidelistChanged()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public void setPermanentPeptideFilter(
          peptideFilterStructure anInPermanentPeptideFilter)
        {

            mPermanentFilter2 = anInPermanentPeptideFilter;
            mPermanentFilter2.tag2 = 0;
            //Calling this function clears "no filter".

            mEffectiveNumberOfPeptides = -1;
            //Flag that we should find effective
            //  number of peptides (but we lazy find it - just before the
            //  number is needed).
        } //setPermanentPeptideFilter()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public void setDefaultSortOrder(peptideSortOrderEnum aSortOrder)
        {
            mSortDefaultOrder = aSortOrder;
        } //setDefaultSortOrder()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public int newIteratorToken(peptideFilterStructure aFilter)
        {
            int toReturn = mIteratorTokenGeneration;
            mIteratorTokenGeneration += 1;

            //Changed PM_REFACTOR 2008-10-30. Generated by VB to C# converted.
            //Disable it for now to stay faithful to the original.
            //iteratorStructure info = default(iteratorStructure);
            //iteratorStructure info;
            iteratorStructure info = default(iteratorStructure); //Use it after all.

            info.readIndex = 0;
            info.lastReadIndex = -99;

            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-29. Needed because
            //of recent changes and some client side call sequences. mPeptides2
            //is nothing if no peptide was added to a protein during parsing.
            //Dim len As Integer = mPeptides2.Count
            int len = 0;
            if (mPeptides2 != null)
            {
                len = mPeptides2.Count;
            }
            else
            {
                int peter2 = 2;
                //Is Nothing...
            }

            int lastIndex = len - 1;
            info.lastIndex = lastIndex;

            info.sortOrder = mSortDefaultOrder;
            info.sortedKeys2 = null;
            //Lazy instantiation of the sorted indexes.

            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-28
            info.filter = aFilter;
            //The assignments to Nothing below
            //  mimics a deep copy (but we don't need to actually copy - unless
            //  we could somehow save on creating a hash each time for the same
            //  peptide filter?).

            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-29
            info.filter.includeModHash_INTERNAL2 = null;
            //Lazy instantiate - only
            //  just before it is needed.

            //Changed PM_EXCLUDE_MODFILTER 2008-06-30
            info.filter.excludeModHash_INTERNAL = null;
            //Lazy instantiate - only
            //  just before it is needed.

            //Changed PM_HIGHESTSCORINGUNIQUELYMODIFIED_BUG 2007-10-05
            info.filter.exHash2_INTERNAL = null;
            //Lazy instantiate - only just
            //  before it is needed.

            if (mIteratorInfo2 == null)
            {
                //Lazy instantiation - for the list of iterators itself.
                mIteratorInfo2 = new Dictionary<int, iteratorStructure>();
            }

            if (!mIteratorInfo2.ContainsKey(toReturn))
            {
                mIteratorInfo2.Add(toReturn, info);
            }
            else
            {
                //This should never happen!
                Trace.Assert(false, "PIL ASSERT. Non-unique key for peptide list iterator.");
            }

            return toReturn;
        } //newIteratorToken()


        //****************************************************************************
        //*    Helper function to avoid suppress compiler warnings.                  *
        //****************************************************************************
        private iteratorStructure emptyIterator2()
        {
            //No longer needed due to use of out keyword?

            //Changed PM_REFACTOR 2008-10-30. Generated by VB to C# converted.
            //Disable it for now to stay faithful to the original.
            //iteratorStructure toReturn = default(iteratorStructure);
            //iteratorStructure toReturn;
            iteratorStructure toReturn = default(iteratorStructure); //Use
            //  it after all.

            //Reference members.
            //Note: compiler gets confused if these lines are
            //  in a "If True" block...
            toReturn.sortedKeys2 = null;
            toReturn.filter.exHash2_INTERNAL = null;

            toReturn.filter.includeModHash_INTERNAL2 = null;

            //Changed PM_EXCLUDE_MODFILTER 2008-06-30
            toReturn.filter.excludeModHash_INTERNAL = null;

            //Changed PM_EXCLUDE_MODFILTER 2008-06-30
            //toReturn.filter.pepModFilter3 = Nothing
            toReturn.filter.pepIncludeModFilter3 = null;
            toReturn.filter.pepExcludeModFilter = null;

            //Other members. Not strictly needed as we don'y presume to
            //initialise everything (but that is what the name of
            //the function suggests).
            toReturn.readIndex = -1;
            //Invalid value. Assume clients are only
            //  tired of compiler warnings and wants to overwrite...

            return toReturn;
        } //emptyIterator2()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public void resetRead(int anIteratorToken)
        {

            Trace.Assert(
              (mIteratorInfo2 != null), "PIL ASSERT. mIteratorInfo is Nothing.");

            ////Changed PM_REFACTOR 2007-12-12
            ////Dim value As iteratorStructure
            //value.sortedKeys2 = Nothing 'Keep compiler happy.
            //iteratorStructure value = emptyIterator();
            ////Keep compiler happy.
            iteratorStructure value;

            if (mIteratorInfo2.TryGetValue(anIteratorToken, out value))
            {
                if (value.readIndex > 0)
                {
                    value.readIndex = 0;
                    mIteratorInfo2[anIteratorToken] = value;
                }
                else
                {
                    //Already at zero, no need to do anything.
                }
            }
            else
            {
                //This should never happen!
                Trace.Assert(
                  false, 
                  "PIL ASSERT. Key does not exist for peptide list iterator.");
            }
        } //resetRead()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        private List<int> getSortedKeys(peptideSortOrderEnum aSortOrder)
        {
            //Note: this gives the order of the ***physical*** list.
            //
            //      This is ***independent*** of any filter that
            //      applies to the list.

            List<int> toReturn = null;

            if (mSortedKeysSet2 == null)
            {
                //Lazy instantiation. Empty, ready to store one keylist per
                //kind of sort order.
                mSortedKeysSet2 = new Dictionary<peptideSortOrderEnum, List<int>>();
            }

            //Do we already have the list of sorted keys?
            List<int> possibleSortedKeys; //  = null;
            if (mSortedKeysSet2.TryGetValue(aSortOrder, out possibleSortedKeys))
            {
                //Changed PM_UNNECESSARY_OPERATION 2008-10-30
                //toReturn = mSortedKeysSet2(aSortOrder);
                toReturn = possibleSortedKeys;
            }
            else
            {
                //Lazy sort... We do not sort until we really have to. That is
                //until this function is called, e.g. through nextPeptide().

                //Sorted keys do not exist for this sort order. Create them.
                int len = mPeptides2.Count;
                int lastIndex = len - 1;
                //ReDim toReturn(lastIndex)

                //Changed PM_TYPESAFE 2006-11-08
                //toReturn = New ArrayList(len)
                toReturn = new List<int>(len);

                //Create keys
                int j = 0;
                for (j = 0; j <= lastIndex; j += 1)
                {
                    toReturn.Add(j);
                }

                //Sort the keys.
                switch (aSortOrder)
                {
                    case peptideSortOrderEnum.enumSequenceThenScore:

                        SortBySequenceThenScore_usingIndex sortObject =
                          new SortBySequenceThenScore_usingIndex( mPeptides2);
                        toReturn.Sort( sortObject);

                        break;

                    default:
                        Trace.Assert(
                            false,
                            "PIL ASSERT. Select Case never fall-through");
                        break;
                }
                mSortedKeysSet2.Add(aSortOrder, toReturn);
            }
            return toReturn;
        } //getSortedKeys()


        //Changed PM_REFACTOR 2006-10-22
        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public static int hashValueForModification(
            List<modificationCountStruct> anInMods2,
            Dictionary<int, int> anInExcludeModsList,
            bool aConsiderModCounts)
        {
            //About anInExcludeModsList:
            //  1. could be SILAC modification.
            //  2. we ignore the value, it is the SILAC dish number (zero based) and
            //     is used by client in other places, but not here...

            int toReturn = 0;

            //Attempt to make unique integer for modification set
            //for the current peptide. Note: is not 100% foolproof...

            if (anInMods2 != null)
            {
                int mult = 2;
                int hashValue = 0;

                //Changed PM_REFACTOR 2008-10-30. Generated by VB to C# converted.
                //Disable it for now to stay faithful to the original.
                //modificationCountStruct someMod = default(modificationCountStruct);

                foreach (modificationCountStruct someMod in anInMods2)
                {

                    int modID = someMod.quantModificationID;

                    //Changed PM_TOOMANY_QUANT_PEPTIDES_BUG 2008-09-10
                    bool acceptMod = 
                        anInExcludeModsList == null || 
                        !anInExcludeModsList.ContainsKey(modID);
                    //Note: depends
                    //   on boolean short-circuit...


                    if (acceptMod)
                    {
                        //Changed PM_SILACDISH_UNIQUELY_HIGHEST_SCORING 2008-10-02
                        int modCountToUse = 1;
                        if (aConsiderModCounts)
                        {
                            modCountToUse = someMod.count3;
                        }
                        else
                        {
                            int peter2 = 2;
                        }

                        //For breakpoints
                        if (modCountToUse > 1)
                        {
                            int peter2 = 2;
                        }

                        int value = mult * modCountToUse * modID;
                        hashValue += value;
                        mult *= 2;
                    }
                    else
                    {
                        int peter3 = 3;
                    }
                }
                toReturn = hashValue;
            }
            else
            {
                //No mods....

                int peter8 = 8;
            }

            return toReturn;
        } //hashValueForModificaiton()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        private void buildKeyForHighestScoring(
            string anInSeq,
            highestScoringParametersStructure anInKeyBuildOptions,
            int aCharge,
            int aFileID,
            List<modificationCountStruct> anInMods2,
            int aSILACdish,
            ref StringBuilder anInOutKeySB)
        {

            //Old name of this function:
            //  highestScoringUniqueModKey()

            //Old:
            //  ByRef anInMods As ArrayList

            if (anInOutKeySB.Length > 0)
            {
                anInOutKeySB.Length = 0;
                //Clear it....
            }

            anInOutKeySB.Append(anInSeq);

            //Changed PM_SILACDISH_UNIQUELY_HIGHEST_SCORING 2008-10-02. Below
            //  are the new options.

            if (anInKeyBuildOptions.differentCharge)
            {
                anInOutKeySB.Append("_");
                anInOutKeySB.Append(aCharge.ToString());
            }

            if (anInKeyBuildOptions.differentRawFile)
            {
                anInOutKeySB.Append("_");
                anInOutKeySB.Append(aFileID);
            }

            //Changed PM_SILACDISH_UNIQUELY_HIGHEST_SCORING 2008-10-02
            //Now optional. Before it was the option and always on ("Only highest
            //scoring uniquely modified").
            if (anInKeyBuildOptions.differentModificationSet)
            {

                anInOutKeySB.Append("_");

                //Changed PM_REFACTOR 2006-10-22. Moved to separate function in
                //order to use it from elsewhere.
                bool considerModificationCounts = 
                  anInKeyBuildOptions.differentModificationCounts2;
                int hashValue =
                    hashValueForModification(
                        anInMods2,
                        anInKeyBuildOptions.differentModification_excludedMods2,
                        considerModificationCounts);

                anInOutKeySB.Append(hashValue.ToString());
            }

            if (anInKeyBuildOptions.differentSILACdish)
            {
                anInOutKeySB.Append("_");
                anInOutKeySB.Append(aSILACdish);
            }
        } //buildKeyForHighestScoring()


        //Dim inModfilter As Boolean = _
        //Changed PM_REFACTOR 2008-06-30. Separate function. To make adding
        //  functionality for exclude modification filter almost trivial.
        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        private static bool isInModFilter(
            List<int> anInPeptideModFilter,
            ref Dictionary<int, int> anInOutModificationHash,
            bool anInValueIfNotSpecified,
            List<massSpectrometryBase.modificationCountStruct> anInModHits,
            out bool anOutUpdateModHash)
        {
            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-29
            bool toReturn = anInValueIfNotSpecified;
            //Default if no mod filter specified.

            //Changed PM_CSHARP_DETECTED_PROBLEM 2008-10-30
            anOutUpdateModHash = false;

            List<int> modFilter = anInPeptideModFilter;
            bool includeModFilterExists = (modFilter != null);

            //Note: depends on short-circuit boolean. Order must be preserved.
            bool modFilterInEffect = includeModFilterExists && modFilter.Count > 0;

            int filterCount = 0;
            if (includeModFilterExists)
            {
                filterCount = modFilter.Count;
                //Require Nothing if not really in effect.
                Trace.Assert(
                    filterCount > 0,
                    "PIL ASSERT. Field pepModFilter3 is empty (but not Nothing).");
            }

            //Any mod filter specified?
            if (modFilterInEffect)
            {
                if (anInOutModificationHash == null)
                {
                    //Lazy instantiation.
                    //
                    anInOutModificationHash =
                        peptideFilterStructure.hashForModFilter(modFilter);

                    //Changed PM_REFACTOR 2007-09-05
                    //If permanentFilter Then
                    //    mPermanentFilter2.modHash_INTERNAL = _
                    //      effectiveFilter.modHash_INTERNAL 'Update the source...
                    //Else
                    //    value.filter.modHash_INTERNAL = _
                    //      effectiveFilter.modHash_INTERNAL
                    //    'Note: write-back for per-iterator is done at
                    //    '      the end of the loop.
                    //End If
                    anOutUpdateModHash = true;
                }

                //Block. For ASSERT only.
                {
                    int count1 = filterCount;
                    int count2 = anInOutModificationHash.Count;

                    //Changed PM_PEPTIDECOUNT_BUG 2007-09-04
                    Trace.Assert(count1 == count2, "PIL ASSERT. " + "Count for field peptideModificationFilter2 " + ", " + count1 + ", is not consistent with count for " + "field modHash_INTERNAL, " + count2 + ".");
                } //Block.

                toReturn =
                    peptideFilterStructure.anyModsInFilter(
                        anInModHits, anInOutModificationHash);
            }
            else
            {
                int peter2 = 2;
                //No mod filter specified.
            } //Any mod-filter.

            return toReturn;
        } //isInModFilter()


        //Changed PM_REFACTOR 2007-09-05
        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public static bool simpleFilteredOut(
            PeptideHitStructure anInPeptide,
            peptideFilterStructure anInOutFilter,
            out bool anOutUpdateIncludeModHash,
            out bool anOutUpdateExcludeModHash)
        {

            //Note: the modhash field in anInOutFilter may be set in this function.

            bool toReturn = true;

            //Changed PM_EXCLUDE_MODFILTER 2008-06-30
            //anOutUpdateModHash = False
            anOutUpdateIncludeModHash = false;
            anOutUpdateExcludeModHash = false;

            int ch = anInPeptide.charge;
            int slen = anInPeptide.AASequence.Length;

            bool peptideMarkedForDeletion = ch == MARKEDFORDELETION_CODE2;

            //For breakpoints.
            if (peptideMarkedForDeletion)
            {
                int peter2 = 2;
            }
            else
            {
                int peter3 = 3;
            }

            //Changed PM_MASCOTSCORE_ASDOUBLE 2008-11-25
            ////Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-26
            //int score = anInPeptide.MascotScore;
            double score2 = anInPeptide.MascotScore2;

            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-28
            //Should we use this value? Mass or MCR? Observed
            //or theoretical.
            double mass = anInPeptide.MascotCalculatedMass;

            //Changed PM_VALIDATION_AFTER_RECALIBRATION 2007-09-24
            //Dim measureMassToUse As Double = anInPeptide.measuredMass
            double measuresMassToUse = anInPeptide.calibratedMeasuredMass;

            if (measuresMassToUse < 10.0)
            {
                measuresMassToUse = mass;
                //Do not consider mass accuracy.
            }
            else
            {
                int peter2 = 2;
            }

            //'Is this defined during parse???
            //Dim massAccuracyRelative As Double = _
            //  (anInPeptide.measuredMass - mass) / mass * 1000000.0
            double massAccuracyRelative = (measuresMassToUse - mass) / mass * 1000000.0;

            bool quantified = PILpeptides.isQuantified(ref anInPeptide);

            bool verified = anInPeptide.verified;
            //??? Should
            //  it be some other field? "Checked" ?

            bool inIncludeModfilter =
                isInModFilter(
                    anInOutFilter.pepIncludeModFilter3,
                    ref anInOutFilter.includeModHash_INTERNAL2,
                    true,
                    anInPeptide.modHits2,
                    out anOutUpdateIncludeModHash);

            bool inExcludeModfilter =
                isInModFilter(
                    anInOutFilter.pepExcludeModFilter,
                    ref anInOutFilter.excludeModHash_INTERNAL,
                    false,
                    anInPeptide.modHits2,
                    out anOutUpdateExcludeModHash);

            //Changed PM_MASSACC_PEPFILTER 2007-09-05. Added to
            //  filter: massAccuracyMin and massAccuracyMax.

            //Changed PM_RAWFILE_PEPFILTER 2007-11-16
            bool inRawFileFilter = true;
            int filterID = anInOutFilter.rawFileID;
            bool activeRawFilterFilter = filterID >= 0;
            if (activeRawFilterFilter)
            {
                inRawFileFilter = 
                    filterID == anInPeptide.rawFileID;
            }

            //Changed PM_SHORTCIRCUIT_BOOL 2008-11-04. The original VB source
            //used "Or" and not "OrElse".
            //
            //Should we reorder so the most likely conditions to be true are
            //listed first?

            //Changed PM_MASCOTSCORE_ASDOUBLE 2008-11-25. For score
            //comparison: no longer integer to double comparison (implicit
            //integer to double conversion).

            toReturn =
                  (ch < anInOutFilter.chargeMin ||
                   ch > anInOutFilter.chargeMax)                         
              ||
                  (slen < anInOutFilter.seqLengthMin ||
                   slen > anInOutFilter.seqLengthMax)
              ||
                  (score2 < anInOutFilter.scoreMin ||
                   score2 > anInOutFilter.scoreMax2)
              ||
                  (mass < anInOutFilter.massMin ||
                   mass > anInOutFilter.massMax)
              ||
                  (anInOutFilter.quantifiedOnly && !quantified)          
              ||
                  (anInOutFilter.verifiedOnly && !verified)              
              ||
                  peptideMarkedForDeletion                               
              ||
                  !inIncludeModfilter                                    
              ||
                  inExcludeModfilter                                     
              ||
                  (massAccuracyRelative < anInOutFilter.massAccuracyMin ||
                   massAccuracyRelative > anInOutFilter.massAccuracyMax) 
              ||
                  !inRawFileFilter                                       
              ||
                false;

            return toReturn;
        } //simpleFilteredOut()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public bool nextPeptide(
            int anIteratorToken,
            out PeptideHitStructure aOutPeptide,
            out int anOutPeptideToken)
        {
            //Future: detect that resetRead() was called.

            bool toReturn2 = false; //Not at EOF

            anOutPeptideToken = -1;

            //Changed PM_KEEP_COMPILER_HAPPY 2008-10-30
            //Keep compiler happy. This function is slower now as a result...
            aOutPeptide = default(PeptideHitStructure);

            bool filteredOut = true;
            //True: at least one time through
            //  the loop below.

            StringBuilder keySB = null;

            if (mIteratorInfo2.ContainsKey(anIteratorToken))
            {
                //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27
                iteratorStructure value = mIteratorInfo2[anIteratorToken];

                //Changed PM_REFACTOR 2008-10-30. Generated by VB to C# converted.
                //Disable it for now to stay faithful to the original.
                //peptideFilterStructure effectiveFilter =
                //    default(peptideFilterStructure);
                peptideFilterStructure effectiveFilter;

                bool permanentFilter =
                    value.filter.tag1 == PILpeptides.MARK_PERMANENT_FILTER2;
                if (permanentFilter)
                {
                    effectiveFilter = mPermanentFilter2;
                }
                else
                {
                    effectiveFilter = value.filter;
                }

                //Changed PM_PEPTIDEFILTER_HIGHESTSCORING 2006-05-19
                //Highest scoring.

                //Changed PM_SILACDISH_UNIQUELY_HIGHEST_SCORING 2008-10-02
                //'If mPermanentFilter.highestScoringUniquelyModified Then
                //If effectiveFilter.highestScoringUniquelyModified Then
                if (effectiveFilter.onlyHighestScoring)
                {
                    //Changed PM_PEPTIDEFILTER_HIGHESTSCORING 2006-05-19

                    //Changed PM_MARKER_FAIL 2007-08-27
                    //This will certainly fail (as there is no hash for
                    //  each iterator, but only one per peptide list instance).
                    //
                    //Possible scenario 1:
                    //  If "highestScoringUniquelyModified"
                    //  is turned off during export for an unsaved parse (that is
                    //  before they physically excluded by save/load) with this
                    //  option on. Then too many peptides will be exported.
                    //  On the other hand: Will the old state from parsing be
                    //                     remembered and thus work anyway?
                    //
                    //  A partial solution could be to physically exclude
                    //  peptides from the protein list already during parsing.
                    //
                    //Possible scenario 2:
                    //  If "highestScoringUniquelyModified" is turned off at parse
                    //  time and on during an export perhaps this state will be
                    //  remembered and reopening a protein validation window will
                    //  display fewer peptides and all subsequently exports will
                    //  also contain too few peptides ?

                    //Changed PM_HIGHESTSCORINGUNIQUELYMODIFIED_BUG 2007-10-05
                    //If mExcludeHash2 Is Nothing Then 'Lazy instantiation
                    if (!mBuildingExcludeHash)
                    {

                        //First time we need to find the highest
                        //scoring uniquely modified peptide in a
                        //protein's list.
                        //
                        //We wait until now to find the best scoring ones.

                        //Changed PM_HIGHESTSCORINGUNIQUELYMODIFIED_BUG 2007-10-05
                        //mExcludeHash2 = New Dictionary(Of String, Integer)
                        //effectiveFilter.excludeHash_INTERNAL = _
                        //  New Dictionary(Of String, Integer)
                        mBuildingExcludeHash = true;

                        //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27. Use of
                        //the other constructor.
                        //Dim pepIter As peptideListIterator = _
                        //  New peptideListIterator(Me)
                        peptideListIterator pepIter =
                          new peptideListIterator(this, effectiveFilter);

                        int peptideToken = 0;

                        Dictionary<string, int> exHash2 =
                          new Dictionary<string, int>();

                        //  Temporary, used when building
                        //  up the hash. We can not change mExcludeHash2 until
                        //  we are done with all peptides; our recursive call
                        //  would not work.

                        keySB = new StringBuilder();

                        //Changed PM_REFACTOR_OUT_IS_YOUR_FRIEND 2008-10-30
                        //PeptideHitStructure somePeptide =
                        //    helper.blankPeptide(); //Keep compiler happy.
                        PeptideHitStructure somePeptide;

                        //Recursive call of nextPeptide() !!. This for finding the
                        //highest scoring uniquely modified peptides. The (zero)
                        //  size mExcludeHash2 element (but existing) is the flag.
                        while (
                          !pepIter.nextPeptide(
                              out somePeptide, out peptideToken))
                        {
                            //Why do we have this call in two places?
                            this.buildKeyForHighestScoring(
                                somePeptide.AASequence,
                                effectiveFilter.highestScoringParameters,
                                somePeptide.charge,
                                somePeptide.rawFileID,
                                somePeptide.modHits2,
                                somePeptide.SILACdishIndex,
                                ref keySB);

                            string key = keySB.ToString();

                            int exVal; // = 0;
                            if (exHash2.TryGetValue(key, out exVal))
                            {
                                int tokenForOld = exVal;

                                double oldScore2 =
                                  this.peptideScoreByToken(tokenForOld);

                                //Changed PM_MASCOTSCORE_ASDOUBLE 2008-11-25.
                                //Was integer to double comparison...
                                if (somePeptide.MascotScore2 > oldScore2)
                                {
                                    //Higher score. Update hash.
                                    exHash2[key] = peptideToken;
                                }
                                else
                                {
                                    //Lower scoring. Ignore it.
                                    int peter8 = 8;
                                }
                            }
                            else
                            {
                                exHash2.Add(key, peptideToken);
                                //Store the physical
                                // index... Are tokens stable enough???
                            }
                        }

                        //Changed PM_HIGHESTSCORINGUNIQUELYMODIFIED_BUG 2007-10-05
                        //mExcludeHash2 = exHash2
                        effectiveFilter.exHash2_INTERNAL = exHash2;
                        //Only now
                        //  can we set it (?).
                        mBuildingExcludeHash = false;
                        //
                        //Is it written back??? Yes, apparently always in the
                        //loop below. Unless at EOF, but then it is not required.

                        //Write-back. We need to remember the hash for
                        //all subsequent calls to this function.
                        if (permanentFilter)
                        {
                            mPermanentFilter2 = effectiveFilter;
                        }
                        else
                        {
                            value.filter = effectiveFilter;
                            mIteratorInfo2[anIteratorToken] = value;
                        }
                    } //if, Building up hash for option highestScoringUniquelyModified.
                }
                else
                {
                    int peter2 = 2;
                    //Not highestScoringUniquelyModified...
                }

                //To end loop either the peptide must
                while (filteredOut)
                {
                    //  be within the filter or at EOF. This way
                    //  we jump to the next peptide within the filter.

                    //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27. Moved to
                    //  beginning of this function.
                    //Dim value As iteratorStructure = mIteratorInfo2(anIteratorToken)

                    int index = value.readIndex;
                    if (index <= value.lastIndex)
                    {
                        if (value.sortedKeys2 == null)
                        {
                            value.sortedKeys2 = this.getSortedKeys(value.sortOrder);

                            int lastIndexSortedKeys = value.sortedKeys2.Count - 1;
                            int readLastIndex = value.lastIndex;
                            Trace.Assert(
                                readLastIndex == lastIndexSortedKeys,
                                "PIL ASSERT. Sorted keys are too short.... " +
                                " Sorted keys last index: " + lastIndexSortedKeys +
                                ". Peptide list last index: " + readLastIndex + ".");
                        }

                        int peptIndex = value.sortedKeys2[index];

                        anOutPeptideToken = peptIndex + mPeptideTokenBase;

                        aOutPeptide = mPeptides2[peptIndex];

                        //Changed PM_REFACTOR 2007-09-05
                        //Apply peptide filter on-the-fly.
                        bool updateIncludeModHash = false;
                        bool updateExcludeModHash = false;
                        filteredOut =
                            simpleFilteredOut(
                                aOutPeptide,
                                effectiveFilter,
                                out updateIncludeModHash,
                                out updateExcludeModHash);

                        if (updateIncludeModHash)
                        {
                            if (permanentFilter)
                            {
                                mPermanentFilter2.includeModHash_INTERNAL2 =
                                    effectiveFilter.includeModHash_INTERNAL2;
                                //Update
                            }
                            //  the source...
                            else
                            {
                                value.filter.includeModHash_INTERNAL2 =
                                    effectiveFilter.includeModHash_INTERNAL2;
                                //Note: write-back for per-iterator is done at
                                //      the end of the loop.
                            }
                        }

                        //Changed PM_EXCLUDE_MODFILTER 2008-06-30
                        if (updateExcludeModHash)
                        {
                            if (permanentFilter)
                            {
                                mPermanentFilter2.excludeModHash_INTERNAL =
                                    effectiveFilter.excludeModHash_INTERNAL;
                                //Update
                            }
                            //  the source...
                            else
                            {
                                value.filter.excludeModHash_INTERNAL =
                                    effectiveFilter.excludeModHash_INTERNAL;
                                //Note: write-back for per-iterator is done at
                                //      the end of the loop.
                            }
                        }

                        //ZZZZ peptides
                        if (!filteredOut)
                        {
                            filteredOut =
                                aOutPeptide.AASequence ==
                                peptideConstants.SEQUENCE_BADPEPTIDE;

                            //For breakpoints
                            if (filteredOut)
                            {
                                int peter1 = 1;
                            }
                            else
                            {
                                int peter2 = 2;
                            }
                        }

                        //Override...
                        //Assumes the significant values
                        if (effectiveFilter.tag2 < 0)
                        {
                            //are negative...
                            //Changed PM_ZAP_PEPTIDES 2006-10-25
                            switch (effectiveFilter.tag2)
                            {
                                case NOFILTER_CODE2:
                                    //Override.
                                    filteredOut = false;
                                    break;

                                //Now handled above.
                                //Case MARKEDFORDELETION_CODE2
                                //    filteredOut = True

                                default:
                                    //We do not accept any other negative
                                    //value.
                                    Trace.Assert(false, "PIL ASSERT. Select Case never fall-through");
                                    break;
                            }
                        }
                        //Filtering enabled.

                        bool considerHighestScoringUniquelyModified =
                            !filteredOut && effectiveFilter.onlyHighestScoring;
                        //effectiveFilter.highestScoringUniquelyModified  old...

                        if (considerHighestScoringUniquelyModified)
                        {
                            //Changed PM_HIGHESTSCORINGUNIQUELYMODIFIED_BUG 2007-10-05
                            //If mExcludeHash2.Count = 0 Then
                            if (mBuildingExcludeHash)
                            {
                                //The hash is being built up: do nothing
                                int peter3 = 3;
                            }
                            else
                            {
                                //Hash is ready to use!

                                if (keySB == null)
                                {
                                    keySB = new StringBuilder();
                                }

                                //Why do we have this call in two places?
                                this.buildKeyForHighestScoring(
                                    aOutPeptide.AASequence,
                                    effectiveFilter.highestScoringParameters,
                                    aOutPeptide.charge,
                                    aOutPeptide.rawFileID,
                                    aOutPeptide.modHits2,
                                    aOutPeptide.SILACdishIndex,
                                    ref keySB);

                                string key2 = keySB.ToString();

                                int value2; // = 0;

                                //Changed PM_HIGHESTSCORINGUNIQUELYMODIFIED_BUG 2007-10-05
                                //If mExcludeHash2.TryGetValue(key2, value2) Then
                                if (effectiveFilter.exHash2_INTERNAL.TryGetValue(
                                      key2, out value2))
                                {

                                    int tokenForPeptideToKeep = value2;

                                    if (anOutPeptideToken != tokenForPeptideToKeep)
                                    {
                                        filteredOut = true;

                                        //Changed PM_HIGHESTSCORINGUNIQUELYMODIFIED_BUG 2007-10-04
                                        //Fix this problem by physically marking
                                        //the peptide so temporary peptide filters
                                        //used later (e.g. for recalibration
                                        //visualisation) will not see it.

                                        if (permanentFilter)
                                        {
                                            PeptideHitStructure.invalidatePeptide(
                                               ref aOutPeptide);

                                            //Write-back.
                                            mPeptides2[peptIndex] = aOutPeptide;
                                        }
                                    }

                                    //But what if the option is set in a
                                    //non-permanent filter???? mExcludeHash2
                                    //is for the entire instance, not
                                    //per iterator.

                                    else
                                    {
                                        int peter8 = 8;
                                        //Current is
                                        //  highest scoring uniquely modified
                                        //  in a protein.
                                    }
                                }
                                else
                                {
                                    Trace.Assert(false, "PIL ASSERT. mExcludeHash2 does " + "not contain key." + key2);
                                    //We have a key for every peptide for now,
                                    //even non-modified ones.
                                }
                            }
                            //User enabled filtering out of lower
                            //       scoring peptides.
                        }
                        //Not filtered out (already).

                        //For breakpoints
                        if (filteredOut)
                        {
                            int peter1 = 1;
                        }
                        else
                        {
                            int peter2 = 2;
                        }

                        //Prepare for next call
                        {
                            value.lastReadIndex = value.readIndex;
                            value.readIndex += 1;
                            mIteratorInfo2[anIteratorToken] = value;
                            //Write back. Do
                            //  we really need to do it this way?
                        } //Block.
                    }
                    else
                    {
                        //At EOF
                        toReturn2 = true;
                        //At EOF
                        filteredOut = false;
                    }
                } //filtered out.
            }
            else
            {
                //This should never happen!
                Trace.Assert(
                    false,
                    "PIL ASSERT. Key, " + anIteratorToken +
                    ", does not exist for peptide list iterator.");
            }

            //Changed PM_MARKER_PEPITERATOR_CLEANUP 2007-09-04
            //We should probably clean up at this point. E.g.:
            //If toReturn = False Then
            //    mIteratorInfo2.Remove(anIteratorToken)
            //End If

            return toReturn2;
        } //nextPeptide()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public void currentPeptide(
            int anIteratorToken, out PeptideHitStructure aOutPeptide)
        {
            //Future: detect that resetRead() was called.

            Trace.Assert(
                false, "Stop!",
                "PIL ASSERT. Internal/development assert for stopping execution......");

            aOutPeptide = default(PeptideHitStructure); //Make compiler happy.
        } //currentPeptide()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public void updateCurrentPeptide(
            int anIteratorToken, PeptideHitStructure anInPeptide)
        {
            //Future: detect that resetRead() was called.

            ////Changed PM_REFACTOR 2007-12-12
            ////Dim value As iteratorStructure
            ////value.sortedKeys2 = Nothing 'Keep compiler happy.
            //iteratorStructure value = emptyIterator();
            ////Keep compiler happy.
            iteratorStructure value;

            if (mIteratorInfo2.TryGetValue(anIteratorToken, out value))
            {
                int index = value.lastReadIndex;
                int peptIndex = value.sortedKeys2[index];
                mPeptides2[peptIndex] = anInPeptide;
            }
            else
            {
                //This should never happen!
                Trace.Assert(false, "PIL ASSERT. Key does not exist for peptide list iterator.");
            }
        } //updateCurrentPeptide()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public void addPeptide(PeptideHitStructure anInPeptide)
        {
            bool addIt = true;
            //Permanent filter set by client?
            if (mPermanentFilter2.tag2 >= 0)
            {
                bool dummy1 = false;
                bool dummy2 = false;
                bool filteredOut =
                    simpleFilteredOut(
                        anInPeptide, mPermanentFilter2, out dummy1, out dummy2);
                if (filteredOut)
                {
                    addIt = false;
                }
                else
                {
                    int peter3 = 3;
                    //OK to add.
                }
            }
            else
            {
                int peter2 = 2;
                //Permanent filter not set.
            }

            //Do not add it if (the simple) permanent filter says it will
            //never be used.
            if (addIt)
            {
                if (mPeptides2 == null)
                {
                    //Lazy instantiation
                    mPeptides2 = 
                      new List<PeptideHitStructure>(mEstimatedCapacity);
                }

                //Changed PM_MEMORY_EFFICIENCY 2007-02-19. Capacity...

                else
                {
                    int peter2 = 2;
                }

                mPeptides2.Add(anInPeptide);

                //Changed PM_COMBINED_INDEXOUTOFRANGE_EXCEPTION 2006-03-27
                this.peptidelistChanged();
                //E.g. existing sorted keys are invalidated. This can happen
                //for correlated files where peptides are inserted later.
            }
            else
            {
                int peter4 = 4;
                //Not added...
            }
        } //addPeptide()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public void peptideByToken(
            int aPeptideToken, out PeptideHitStructure aOutPeptide)
        {

            int peptIndex = aPeptideToken - mPeptideTokenBase;

            int lastIndex = mPeptides2.Count - 1;
            if (peptIndex >= 0 && peptIndex <= lastIndex)
            {
                aOutPeptide = mPeptides2[peptIndex];
            }
            else
            {
                //Token is probably not given by this class. Leave the return
                //peptide undefined. Should we set some fields??
                aOutPeptide = default(PeptideHitStructure);
            }
        } //peptideByToken()


        //Convenience function for clients
        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public double peptideScoreByToken(int aPeptideToken)
        {

            PeptideHitStructure pept = PeptideHitStructure.blankPeptide();
            //Keep compiler happy.

            this.peptideByToken(aPeptideToken, out pept);

            //Changed PM_MASCOTSCORE_ASDOUBLE 2008-11-25. No longer implicit
            //integer to double conversion...
            return pept.MascotScore2;
        } //peptideScoreByToken()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public void updatePeptideByToken(
            int aPeptideToken, PeptideHitStructure anInPeptide)
        {
            int peptIndex = aPeptideToken - mPeptideTokenBase;

            mPeptides2[peptIndex] = anInPeptide;
            //Could this not fail
            //  if one of the fields for sorting has been changed by
            //  the client??.
        } //updatePeptideByToken()


        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public int peptideCount2(int anIteratorToken)
        {
            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27
            //Count depends on the filter! - per iterator...

            //Note: the returned value is not necessarily the physical number
            //      of peptides as we may be hiding some, e.g. ZZZZ peptides.
            //
            //Uses default filter (or current filter?).

            int toReturn = 0;

            bool doContinue = true;
            if (mPeptides2 != null)
            {
                toReturn = mPeptides2.Count;
                //Default, if not applying
            }
            //peptide filter(s).
            else
            {
                doContinue = false;
                //This can happen if no peptides
                //  were added.
            }

            if (doContinue)
            {
                //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27
                iteratorStructure value = mIteratorInfo2[anIteratorToken];

                //Changed PM_REFACTOR 2008-10-30. Generated by VB to C# converted.
                //Disable it for now to stay faithful to the original.
                //peptideFilterStructure effectiveFilter = default(peptideFilterStructure);
                peptideFilterStructure effectiveFilter;

                bool permanentFilter = 
                    value.filter.tag1 == PILpeptides.MARK_PERMANENT_FILTER2;

                if (permanentFilter)
                {
                    effectiveFilter = mPermanentFilter2;
                }
                else
                {
                    effectiveFilter = value.filter;
                }

                if (effectiveFilter.tag2 >= 0)
                {
                    //That is: a peptide filter is in effect (permanent or not).

                    int effectiveNumberOfPeptides = 0;
                    if (permanentFilter)
                    {
                        effectiveNumberOfPeptides = mEffectiveNumberOfPeptides;
                    }
                    else
                    {
                        effectiveNumberOfPeptides = value.effectiveNumberOfPeptides;
                    }

                    //If mEffectiveNumberOfPeptides < 0 Then
                    if (effectiveNumberOfPeptides < 0)
                    {
                        //Find the effective number of peptides given the
                        //current peptide filter...

                        int count = 0;

                        //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-28
                        //Dim pepIter As peptideListIterator = _
                        //  New peptideListIterator(Me)

                        //Changed PM_REFACTOR 2008-10-30. Generated by VB to C# converted.
                        //Disable it for now to stay faithful to the original.
                        //peptideListIterator pepIter = default(peptideListIterator);
                        peptideListIterator pepIter;
                        if (permanentFilter)
                        {
                            pepIter = new peptideListIterator(this);
                        }
                        else
                        {
                            pepIter = new peptideListIterator(this, value.filter);
                        }

                        PeptideHitStructure pept; // = helper.blankPeptide();
                        while (!pepIter.nextPeptide(out pept))
                        {
                            count += 1;
                        }

                        //Should this be in the if clause below?.
                        value.effectiveNumberOfPeptides = count;
                        mIteratorInfo2[anIteratorToken] = value;

                        if (permanentFilter)
                        {
                            mEffectiveNumberOfPeptides = count;
                        }
                        else
                        {
                            int peter2 = 2;
                        }

                        effectiveNumberOfPeptides = count;
                    }
                    else
                    {
                        //Already computed. Just use the cached value.
                        int peter2 = 2;
                        //For breakpoints.
                    }

                    //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-28
                    //toReturn = mEffectiveNumberOfPeptides
                    toReturn = effectiveNumberOfPeptides;
                }
                else
                {
                    int peter2 = 2;
                    //No filter...
                }
            } //If continue.

            //Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-29

            Trace.Assert(
                toReturn >= 0, 
                "PIL ASSERT. Negative value of peptide count: " + toReturn + ".");

            return toReturn;
        } //peptideCount2()


        //Changed PM_ZAP_PEPTIDES 2006-10-25
        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public void zapPeptides_queryRange(int aQueryStart, int aQueryEnd)
        {
            //Note: for now we only mark it for deletion. Later
            //  we should also physically delete, e.g. if
            //  more than 10 percent of the peptides have been
            //  marked for deletion.

            //We could use nextPeptide() instead...

            int lastIndex = mPeptides2.Count - 1;
            int j = 0;

            //Linear search... Hopefully there are not too many peptides.
            for (j = 0; j <= lastIndex; j += 1)
            {
                PeptideHitStructure pept = mPeptides2[j];
                int query = pept.queryNumber;

                if (query >= aQueryStart && query <= aQueryEnd)
                {

                    pept.charge = MARKEDFORDELETION_CODE2;
                    //We mark the
                    //  peptide for deletion by assigning a non-valid
                    //  valid to one of the peptide's fields.

                    mPeptides2[j] = pept;
                }
                else
                {
                    int peter2 = 2;
                }
            }

            this.peptidelistChanged();
            //E.g. existing sorted keys are invalidated. This
            //  can happen for correlated files where peptides are inserted later.
        } //zapPeptides_queryRange()


        //Changed PM_REFACTOR 2007-08-26
        //Should this function be here???? It is related to a
        //single peptide, not a list of them...
        //****************************************************************************
        //*    <placeholder for header>                                              *
        //****************************************************************************
        public static bool isQuantified(ref PeptideHitStructure anInPept)
        {
            bool quantified = false;
            if (anInPept.LCprofilesProperties != null)
            {
                int effectiveIndex = -1;
                int count = anInPept.LCprofilesProperties.Count;
                if (count >= 2)
                {
                    effectiveIndex = 1;
                    //Second dish/heavy isotope.
                }
                else
                {
                    //Changed PM_EXPORT_BUG_QUANTIFIED_NO_ISOTOPE 2007-01-08
                    if (count == 1)
                    {
                        //No isotope.
                        effectiveIndex = 0;
                    }
                    else
                    {
                        //This should never happen...
                        Trace.Assert(
                            false, "Stop!", 
                            "PIL ASSERT. " + 
                            "Internal/development assert for stopping execution......");
                    }
                }

                LCprofilesPropertiesStructure dish1props =
                    anInPept.LCprofilesProperties[effectiveIndex];
                quantified =
                    dish1props.averageOfRatios2 > 1E-08 &&
                    anInPept.useForQuantitation;
            }
            else
            {
                int peter9 = 9;
                //Has not been quantified....
            }

            return quantified;
        } //isQuantified()


    } //class PILpeptides

} //massSpectrometryBase

    

    

Generated by script codePublish.pl at 2009-01-05T15:20:59.