Source code for MSQuant: MascotResultParser.vb, MSQuant/msquant/src/main/MascotResultParser.vb.

Table of contents page.

Home page for MSQuant.

'****************************************************************************
'* Copyright (C) 2004 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: Class that can parse Mascot result files (HTML).                *
'*                                                                          *
'****************************************************************************

'****************************************************************************
'*                               CEBI                                       *
'*                    Software Development Group                            *
'*                         Peter Mortensen                                  *
'*                E-mail: NUKESPAMMERSdrmortensen@get2netZZZZZZ.dk          *
'*                 WWW: http://www.cebi.sdu.dk/                             *
'*                                                                          *
'*  Program for postprocessing of MS-MS search result                       *
'*                                                                          *
'*    FILENAME:   MascotResultParser.vb                                     *
'*    TYPE:       VISUAL_BASIC                                              *
'*                                                                          *
'* CREATED: MM 2002-05-15   Vrs 1.0. Estimated date.                        *
'* UPDATED: PM 2003-xx-xx                                                   *
'*                                                                          *
'****************************************************************************

Option Strict On
Option Explicit On  'Changed PM_OPTIONEXPLICIT 2003-02-13

'The job of this class is to do all the parsing of a Mascot web output page
'It communicates with a companion form which displays parsing progress, 
'the final result etc.

Imports System.Text.RegularExpressions
Imports System.Text
Imports System.IO 'For Path class/functions

Imports massSpectrometryBase

Imports massSpectrometryBase.quantitation

Imports MolecularSharedStructures

Imports MSQuant 'For class quantApplication

Imports SDUPutility 'For PILInputOutput.pushToFile

Imports utilityStatic 'For numbersClose

Imports SDUPrecalibrator 'For recalibDomainEnum


#Region "Data and structures."

'Data structure to hold information associated with
'one LC/MS/MS (".wiff", ".raw" or ".idx") file.
<Serializable()> _
Public Structure rawFileInfoStruct

    Dim rawFilePath As String
    Dim sampleNumberInRawFile As Integer
    Dim MascotFilePath As String 'Associated mascot htm search result.

    'Calibration constants for this wiff file for recalibaration.
    Dim a As Double
    Dim b As Double

End Structure 'rawFileInfoStruct


'Old version, up until 2003-08-19. ***Only*** used for reading in an
'old (XML) options file.....
<Serializable()> _
Public Structure OptionsStruct 'Old...
    Dim scoreA As Integer
    Dim scoreB As Integer
    Dim scoreC As Integer
    Dim dontShowIPI As Boolean
    Dim dontShowMosquito As Boolean
    Dim dontShowProtWithNoPeptInABC As Boolean
    Dim inclBoldRedPepts As Boolean
    Dim inclLightRedPepts As Boolean
    Dim inclRedPeptsIfCheckedOnly As Boolean
    Dim inclBoldBlackPeptsIfChecked As Boolean
    Dim inclBoldBlackPepts As Boolean
    Dim inclPeptsInParens As Boolean
    Dim protDefaultValidation As Integer
    Dim peptDefaultValidation As Integer

    'Changed PM_GENERALISED_QUANT_MODE 2003-12-07
    'Dim quantMode As quantModeEnum   Reenabled later

    'Changed PM_PERSIST_OPTIONS 2003-04-14
    Dim checkSum As Integer 'Not a checksum, but a constant field used
    '  for error detection.
End Structure 'OptionsStruct


Public Enum peptideFilterEnum
    enumParsing2 = 353
    enumExport2

    enumRecalibVisual
    enumRecalibParse
    enumValidationParse


    enumRetrieveProteinSequences


    'Later:
    '  enumProtValView
End Enum 'peptideFilterEnum


'Changed PM_HIDE_RECALIBVISUALISATION_WINDOW 2008-01-06
Public Structure endOfParseActionStructure

    Dim openRecalibrationVisualisationWindow As Boolean

End Structure 'endOfParseActionStructure


'Changed PM_FINNEGAN_RAWFILEMODE 2003-08-18. Completely new structure
'to circumvent versioning problems with XML options file.
' <http://www.15seconds.com/issue/020903.htm>:
'   "The only control you have over this process is by using 
'   the [NonSerialized()] field attributes to stop any field 
'   from being serialized. "
<Serializable()> _
Public Structure OptionsStruct2

    Dim inclBoldRedPepts As Boolean
    Dim inclLightRedPepts As Boolean
    Dim inclRedPeptsIfCheckedOnly As Boolean
    Dim inclBoldBlackPeptsIfChecked As Boolean
    Dim inclBoldBlackPepts As Boolean
    Dim inclPeptsInParens As Boolean

    'These 3 are being phased out. They are now effectively
    'in a peptide filter
    Dim peptDefaultValidationScoreThr2 As Integer 'Still integer...
    'Changed PM_PRESELECTEDVALIDATED_CONDITIONS 2004-06-21
    Dim peptideMaximumRelativeError_PPM2 As Double
    Dim peptideMinimumDeltaScore2 As Double

    Dim scoreA As Integer 'Still integer...
    Dim scoreB As Integer 'Still integer...
    Dim scoreC As Integer 'Still integer...

    Dim protDefaultValidationScoreThr As Integer 'Still integer...

    'Changed PM_GENERALISED_QUANT_MODE 2003-12-07
    'Dim quantMode As quantModeEnum   reenable later to not delete any fields.
    Dim quantModeCode As Integer

    'Changed PM_PERSIST_OPTIONS 2003-04-14
    Dim checkSum As Integer 'Not a checksum, but a constant field used
    '  for error detection.

    'Changed PM_FINNEGAN_RAWFILEMODE 2003-08-18
    Dim rawFileMode As rawFileModeEnum

    'Changed PM_MSTYPES_FOR_QUANT_OPTION 2004-09-13
    Dim MStypes As QuantMSTypesEnum 'For quantitation: whether to include
    '  MS spectra of type SIM (Finnigan only), of type
    '  full scan (Finnigan only) or both/all.

    'Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-24. Now much more than 
    '  modification filter. And we have several sets, one for parsing, one
    '  for export, several for different views.
    '
    ''Changed PM_TYPESAFE 2007-08-23
    ' ''Changed PM_MODIFICATION_FILTER 2004-12-07
    ''Dim peptideModificationFilter As ArrayList 'Type is: Integer  
    'Dim peptideModificationFilter2 As Generic.List(Of Integer)
    ''Changed PM_PEPTIDE_FILTER 2006-03-20
    'Dim peptideFilterSpecification As peptideFilterSpecificationStructure
    Dim peptideFilters As _
      Generic.Dictionary( _
        Of peptideFilterEnum, peptideFilterStructure)

    'Changed PM_TITLELINEPARSING 2007-06-08
    Dim TITLEparseDefsCode As Integer

    'Changed PM_REPORTS 2006-08-15
    Dim doNotShowDialogAfterParsing As Boolean

    'Changed PM_COMVERSIONS 2007-07-24
    Dim COMversion As COMversionEnum

    'To be deleted...
    Dim dontShowIPI As Boolean
    Dim dontShowMosquito As Boolean
    Dim dontShowProtWithNoPeptInABC As Boolean

    'Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-29
    Dim exportSettings As proteinAndPeptidesFilterStructure2 'Note that
    '  the peptide filter for export is stored separately, in
    '  field peptideFilters (with a certain key).

    'Changed PM_QUANT_ALL 2007-10-12
    Dim extra2 As String 'For hidden user choices. Generally list of options separated by commas. 

    'Changed PM_DOMAINS_RECALIBRATION 2007-11-06
    Dim recalibDomain As recalibDomainEnum

    'Changed PM_HIDE_RECALIBVISUALISATION_WINDOW 2008-01-06
    Dim endOfParseAction As endOfParseActionStructure

    'Changed PM_RECALIB_REALITY_CHECK 2008-03-26
    Dim recalibLimits As recalibLimitsStructure
End Structure 'OptionsStruct2



'The differences in colour codes are:
'
'a. bold red;  first ranked peptide, used for the first time 
'              in the list.
'
'b. light red; first ranked peptide (identical score to the 
'              bold red), used for 'the second time in the 
'              list, this is the case for redundant proteins 
'              eg 'hemoglobin chains.
'
'c. v light red (peptide is marked by a v) first ranked 
'              peptide which has been used higher in the list 
'              as a second or third or.. ranked peptide with 
'              a lower score. In a lot of cases the peptide 
'              does not belong to the protein higher in the 
'              list where it is not used as a first ranked 
'              peptide but to the protein where it is used as 
'              a first ranked peptide.


Structure TTQueryStruct
    Dim queryNo As Integer
    Dim period2 As Integer
    Dim experimentNumber As Integer 'PM: what is the semantic?
    Dim cycle As Integer
    Dim startElutionTime As Double
    Dim endElutionTime As Double

    'Changed PM_FINNEGAN_RETENTION_TIME 2003-11-18
    Dim spectrNumb As Integer

    Dim seq1 As String
    Dim seq2 As String
    Dim score1 As Double
    Dim score2 As Double
    Dim modLocSeq1 As Integer 'Where is the sequence modified (zero
    '  based location)
    Dim modLocSeq2 As Integer
    Dim seq1Unique As Boolean 'Is this sequence unique in the database?
    Dim seq2Unique As Boolean

    'Changed PM_SEVERALWIFFS 2003-08-26
    Dim qRawFileID As Integer

    'Changed PM_PRECURSOR_INTENSITY 2005-09-08
    Dim precursorIntensity As Double

End Structure 'TTQueryStruct


'Changed PM_SEVERALWIFFS 2003-08-26
Structure rawFileMapStruct
    Dim ID As Integer
    Dim fileNameFullPath As String
End Structure 'rawFileMapStruct


'****************************************************************************
'd$ <summary>
'd$   Purpose: holds simple values about a protein, as parsed from a 
'd$      Mascot HTML file. It is a subset of the fields in
'd$      a MolecularSharedStructures.ProteinHitStructure
'd$     
'd$  
'd$ </summary>
Public Structure simpleProteinInfoStructure

    'd$ <summary>XYZ.</summary>
    Dim accessionNumber As String

    'd$ <summary>XYZ.</summary>
    Dim mass As Double

    'd$ <summary>XYZ.</summary>
    Dim totalScore As Integer

    'd$ <summary>XYZ.</summary>
    Dim totalPeptides As Integer

    'd$ <summary>XYZ.</summary>
    Dim description As String
End Structure 'simpleProteinInfoStructure


'example
'<TR>
'  <TD> </TD>
'  <TD noWrap><TT> <A 
'    href="http://130.225.136.222/mascot/cgi/peptide_view.pl?file=../data/20020703/F003024.dat&query=265&hit=3&index=MAL12P1%2e63%2cPFL0315c&px=1" 
'    onmouseout=clearEl() 
'    onmouseover="statusString = h108_q265; if (NS4 || IE4) activateEl('Q265', event)" 
'    target=_blank>265</A>   <B>464.7601   927.5045   927.4232   0.0813    0    10     3    ENNMVGHK</B></TT></TD></TR>
'<TR>
#End Region


Public Class MascotResultParser

    Public Enum parsingPhaseEnum
        enumReadingFile = 241
        enumParsingToolTips
        enumParsingProteins
        enumOtherParsingXYZ
        enumParsingError
    End Enum

    'Changed PM_PARSE_CHUNKED 2004-04-06
    'This struct exists to group information needed by chunked parsing.
    Private Structure parsingInputStruct
        'Input
        Dim mascotResultFileToParse As String
        Dim rawFilePath As String
        Dim sampleNum As Integer
        Dim options As OptionsStruct2
        Dim corrSettings As massSpectrometryBase.correlationSettingsStructure

        'State
        Dim majorState As parsingPhaseEnum
        Dim bytesInResultFile As Long
        Dim rawBytesRead As Integer

        'Common
        Dim chunkerParsing As SDUPchunker

        'Reading file
        Dim inputFileStream As FileStream  'Is it necessary to keep
        '  this file stream alive?
        Dim inputStreamReader As StreamReader
        Dim fileContent As StringBuilder

        'Tooltip parsing

        'Changed PM_MEMORY_ALLOCATION 2004-07-27
        'Dim toolTipItems As String() 'We no longer store: it takes up
        '  memory (though temporary), slows down things and most of all
        '  puts a strain on the memory allocator and garbage collector.

        Dim toolTips As Integer

        'Error handling
        Dim numToolTipParseErrors2 As Integer
        Dim toolTipErrMsg2 As String

        'Protein parsing
        Dim matchCol As MatchCollection
        Dim firstHitNumber As Integer
        Dim numProteinsParsed As Integer

        'Changed PM_EVENMORE_GENERALISED_QUANTMODES 2005-04-08. Not needed anymore.
        'Dim quantValues As massSpectrometryBase.quantValuesStructure

        Dim proteinsInTable As Integer
    End Structure 'parsingInputStruct


    Public Structure parsingStatsStructure
        Dim curState As parsingPhaseEnum

        Dim bytesReadInThisChunk As Integer

        'Changed PM_PARSEERROR_HANDLING 2004-12-13
        Dim parsingErrorInfo As String


        '1. Add error info:,  e.g. no tool tip section.
        'Propagate all error information - completing the chunk'ing of parsing...
        '
        'Loc:   mChunkedParsingInfo.toolTipErrMsg = "No queries with tool tip information"
    End Structure 'parsingStatsStructure


    '  #Region "Private instance variable and accessors"
    'the option structure should be passed in from the main form?
    Private mParseOptions As OptionsStruct2
    'the Web page as a text string. This can be 10 Mbyte or more
    'should release this once we are done with parsing

    'Changed PM_TYPESAFE 2007-08-29
    ''Changed PM_MODIFICATION_FILTER 2004-12-07
    'Dim mModHash As Hashtable
    Private mModHash2 As Generic.Dictionary(Of Integer, Integer) 'Content will 
    '  be derived from mParseOptions.peptideModificationFilter.
    '  Key is modID and value does not matter/is not used.

    Private mMascotResStr As String
    '  Reference to the main form to report back if necessary (for 
    '  example for progress dialog).

    'Changed PM_REFACTOR 2004-04-06. No longer needed or wanted. Client
    '  will themselves take care of progress, etc.
    'Private mFrmProteinList As frmProteinList
    ' holds the list of ProteinHitStructures

    'Changed PM_TYPESAFE 2006-10-25
    'Private mParsedProts As New ArrayList(1000)
    Private mParsedProts2 As New Generic.List(Of ProteinHitStructure)(1000)

    'List of query structures from parsing "tool tips" at
    'bottom of Mascot page.
    Private mTtQueryArr() As TTQueryStruct

    'Changed PM_SEVERALWIFFS 2003-08-26
    'Private mRawFileMapArr() As rawFileMapStruct

    Private mRawFiles() As massSpectrometryBase.fileSpecStructure

    'Changed PM_CORR_RETENTIONTIME 2003-09-11
    'Member: for it to be global for class.
    Private mRetentionTimeCorrelator As massSpectrometryBase.retentionTimeCorrelator

    'Changed PM_TRIPLE_LYSINE 2003-11-26
    ''Changed PM_ARG6ARG10_ASSERT 2003-10-20
    'Private mArg6Arg10Counter As Integer
    Private mMultModCounter As FindLCpeaks.multModCounterStructure

    'Changed PM_REFACTOR 2003-11-21
    Private mMultipleRawFilesHandling As MultipleRawFilesHandling

    'Changed PM_GENERALISED_QUANT_MODE 2003-12-07
    Private mApplication As quantApplication

    'Changed PM_PARSE_CHUNKED 2004-04-06
    Private mChunkedParsingInfo As parsingInputStruct

    'Changed PM_MEMORY_PROBLEM 2004-04-14
    Private mLogger As SDUPlogger

    'Changed PM_MEMORY_ALLOCATION 2004-07-27
    Private mCurrentIndexIntoHTML As Integer

    'Changed PM_MEMORY_ALLOCATION 2004-07-31
    Private mFilteredPepLinesSB As StringBuilder

    'Changed PM_REPORTS 2006-08-15
    Private mParseReport As SDUPstructuredReport

    'Changed PM_TYPESAFE 2007-08-08
    ''Changed PM_MOD_STATS 2006-08-15
    'Private mRawModStats As Hashtable
    'Private mNoRecognisedModStats As Hashtable
    'Private mRecognisedModStats As Hashtable

    Private mRawModStats2 As Generic.Dictionary(Of String, Integer)
    Private mNoRecognisedModStats2 As Generic.Dictionary(Of String, Integer)
    Private mRecognisedModStats2 As Generic.Dictionary(Of Integer, Integer)

    'Changed PM_MASCOT22_OLDERFORMATS 2007-04-12
    Private mParseMarker_New As String = "  "
    Private mParseMarker_Old As String = " "

    Private mTITLElineParsing As TITLElineParsingStructure


    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Public Sub New( _
      ByRef anApp As quantApplication, _
      ByRef anInOutParseReport As SDUPstructuredReport)

        'Changed PM_CORR_RETENTIONTIME 2003-09-11
        'Member: for it to be global for class.
        'Note: we have no choice for the parameter, the LC profile
        '      centroid is not available at parse time...
        mRetentionTimeCorrelator = _
          New massSpectrometryBase.retentionTimeCorrelator( _
            retentionTimeTypeEnum.enumMSMSevent)

        mApplication = anApp

        'Changed PM_REPORTS 2006-08-15
        mParseReport = anInOutParseReport

        'Changed PM_MOD_STATS 2006-08-15
        mRawModStats2 = New Generic.Dictionary(Of String, Integer)
        mNoRecognisedModStats2 = New Generic.Dictionary(Of String, Integer)
        mRecognisedModStats2 = New Generic.Dictionary(Of Integer, Integer)

        'Changed PM_MEMORY_PROBLEM 2004-04-14
        mLogger = New SDUPlogger
        mLogger.enableLogging()

        mMascotResStr = ""

        'Changed PM_DEFAULT_SAVENAME 2004-10-27
        mChunkedParsingInfo.mascotResultFileToParse = ""
    End Sub 'New


    'Changed PM_REFACTOR 2004-04-06
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Public Function getParsedProteins() _
    As Generic.List(Of ProteinHitStructure)
        'Old return value:
        '  As ArrayList

        Return mParsedProts2
    End Function 'getParsedProteins


    'Changed PM_PARSE_CHUNKED 2004-04-06
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Public Sub initParsingProcessing( _
      ByVal aMascotResultFileToParse As String, _
      ByVal anInRawFilePath As String, _
      ByVal aSampleNum As Integer, _
      ByVal anInOptions As OptionsStruct2, _
      ByRef aCorrSettings As massSpectrometryBase.correlationSettingsStructure)

        'Later: error reporting for failure to open file, etc.

        'Changed PM_PARSE_TROUBLE_OPENTWICE 2007-05-18
        mChunkedParsingInfo.majorState = parsingPhaseEnum.enumParsingError 'In
        '  case we don't reach the end of this function due to an
        '  exception. Otherwise we will get an assert error in doChunkParsing(), 
        '    "PIL ASSERT. Select Case never fall-through".

        'Input
        mChunkedParsingInfo.mascotResultFileToParse = aMascotResultFileToParse
        mChunkedParsingInfo.rawFilePath = anInRawFilePath
        mChunkedParsingInfo.sampleNum = aSampleNum
        mChunkedParsingInfo.options = anInOptions
        mChunkedParsingInfo.corrSettings = aCorrSettings

        'Changed PM_MEMORY_ALLOCATION 2004-07-26. Moved up to use for
        'preallocating for fileContent.
        Dim fi As FileInfo = New FileInfo(aMascotResultFileToParse)
        Dim inputFileLen As Long = fi.Length()
        mChunkedParsingInfo.bytesInResultFile = inputFileLen

        'Moved up here.
        'Changed PM_MEMORY_ALLOCATION 2004-07-26
        ''Changed PM_MEMORY_PROBLEM 2004-04-14
        Trace.Assert(mChunkedParsingInfo.bytesInResultFile > 0, _
          "PIL ASSERT. mChunkedParsingInfo.bytesInResultFile is zero!")

        If True Then 'Try to open file
            Dim errMsg As String = "Could not open the Mascot result file, " & _
              aMascotResultFileToParse
            Try
                'Changed PM_READONLYFILE_BUG 2003-02-09
                'stream = New FileStream(aMascotWiffFileAss.MascotFileStr, FileMode.Open)
                mChunkedParsingInfo.inputFileStream = _
                  New FileStream( _
                    aMascotResultFileToParse, FileMode.Open, FileAccess.Read)

                Dim capacityToUse As Integer = _
                  CInt(mChunkedParsingInfo.bytesInResultFile) + 50000

                'capacityToUse = CInt(capacityToUse / 2)   Test only !!!!

                'Note: can already fail in construction of StringBuilder if the
                '      the result file is too large.
                mChunkedParsingInfo.fileContent = New StringBuilder(capacityToUse)

            Catch exceptionObject As Exception
                'Happend for:
                '  1. a read-only file. Exception type 
                '     System.UnauthorizedAccessException (not mentioned below). 
                '     Above instantiantion has now been changed to use signature 
                '     New(String, FileMode, FileAccess) instead of New(String, 
                '     FileMode) - 
                '
                '  2. If the file does not exist.... - the user is allowed to 
                '     double-click on files that does not exist. Most likely to 
                '     happen when moving from system to system.
                '
                'Note: specifies the possible exceptions:
                '  <ms-help://MS.VSCC/MS.MSDNVS/cpref/html/frlrfsystemiofilestreamclassctortopic2.htm>

                'Changed PM_PARSE_TROUBLE_OPENTWICE 2007-05-18
                'MsgBox(errMsg)
                MSQuantCommon2.displayStandardExceptionInfo( _
                  exceptionObject, _
                  errMsg)

                Exit Sub
            End Try

            Try
                mChunkedParsingInfo.inputStreamReader = _
                  New StreamReader(mChunkedParsingInfo.inputFileStream, _
                    System.Text.Encoding.ASCII)
                '  System.Text.Encoding.ASCII
                '  System.Text.Encoding.UTF8  -default but 2 bytes would be missing in the example file.
                '
            Catch exceptionObject As Exception

                'What kind of exceptions are most likely here?
                MsgBox(errMsg)

                Exit Sub
            End Try
        End If 'Open file

        Dim timeSliceSecs As Double = 2.0
        timeSliceSecs = 0.8
        timeSliceSecs = 0.4
        mChunkedParsingInfo.chunkerParsing = New SDUPchunker(timeSliceSecs)

        'State
        mChunkedParsingInfo.majorState = parsingPhaseEnum.enumReadingFile

        mChunkedParsingInfo.rawBytesRead = 0

        mChunkedParsingInfo.numToolTipParseErrors2 = 0
        mChunkedParsingInfo.toolTipErrMsg2 = Nothing 'Make sure we don't do
        '  unnecessarty string copying...

        mChunkedParsingInfo.chunkerParsing.Init(0, 9999999, True) 'We 
        '  don't know exactly how many file chunks there are so we just set it
        '  to a high number. Relative progress can be computed on the basis
        '  of read bytes.
    End Sub 'initParsingProcessing


    'Changed PM_PARSE_CHUNKED 2004-04-07
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '*    Helper function                                                       *
    '****************************************************************************
    Private Sub tooltipParsingInit( _
          ByVal aOptions As OptionsStruct2, _
          ByVal aRawFilePath As String, _
          ByVal aSampleNum As Integer _
          )

        Trace.Assert(aRawFilePath <> "", _
          "PIL ASSERT. Unexpected empty path, aRawFilePath.")

        mMultModCounter.totalPeptides = 0
        mMultModCounter.peptidesWithModificationForQuantMode = 0
        mMultModCounter.nonMatchingAAsToModificationCountFromMascot = 0

        'Changed PM_QUANTGENERAL_PREPARATION 2006-07-17
        mMultModCounter.sampleQueryNumberForNonMatchingAAs = -1 'Flag for none.

        mParseOptions = aOptions

        'Changed PM_TITLELINEPARSING 2007-06-08
        If True Then
            Dim settings As miscSettingsStructure2Struct = _
              mApplication.getMiscSettings()
            Dim TITLElineDefs As TITLElineDefinitions = _
              settings.TITLElineDefs

            Dim code As Integer = aOptions.TITLEparseDefsCode
            Dim someItem As TITLElineParsingStructure = _
              TITLElineDefs.getTITLElineParseDef(code)

            Trace.Assert( _
              someItem.ID3 >= 0, _
              "PIL ASSERT. Undefined TITLE line definition. Code/ID: " & code)

            mTITLElineParsing = someItem
        End If

        'Convert peptide mod list into a convenient form (a hash).
        If True Then
            'Create hash for easier check.

            'Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-24
            'Dim pepModList As Generic.List(Of Integer) = _
            '  mParseOptions.peptideModificationFilter2
            Dim parsePeptideFilter As peptideFilterStructure = _
              mParseOptions.peptideFilters(peptideFilterEnum.enumParsing2)

            'Changed PM_REFACTOR 2007-08-29
            'Dim pepModList As Generic.List(Of Integer) = _
            '  parsePeptideFilter.peptideModificationFilter2
            'mModHash2 = New Generic.Dictionary(Of Integer, Integer)
            'Dim modID As Integer
            'For Each modID In pepModList
            '    mModHash2.Add(modID, 1)
            'Next
            mModHash2 = _
              peptideFilterStructure.hashForModFilter( _
                parsePeptideFilter.pepModFilter3)
        End If

        'Changed PM_REFACTOR 2003-11-21
        mMultipleRawFilesHandling = New MultipleRawFilesHandling( _
          mParseOptions.rawFileMode, _
          mApplication, _
          mParseOptions.COMversion)

        'Changed PM_IRINA_SAMPLE_NUMBER_TROUBLE 2003-12-02
        mMultipleRawFilesHandling.SetGeneralSampleNumber(aSampleNum)

        mParsedProts2.Clear()
        Dim T1 As Date = Now()
        'First we extract all interesting information in the tool tips
        'at the bottom.

        'Changed PM_REFACTOR 2003-11-21
        'Dim outPeriodRawFiles As Hashtable
        'ToolTipExtrErrors = Me.ParseToolTips(outPeriodRawFiles)
        mMultipleRawFilesHandling.SetBaseDirFromFullFileNamePath(aRawFilePath)

        'Mascot 1.x:
        '  <DIV class=tooltip id=Q1>
        'Some bad Mascot 2.0 formatted:
        '  <DIV CLASS='tooltip' ID='Q1'>
        '
        'Old, no tooltip detection and bad memory.
        'Changed PM_MASCOT1.9_TROUBLE 2003-04-22
        'result = Regex.Match(mMascotResStr, "<DIV class=tooltip id=Q1><PRE>To")
        Dim noErrors As Boolean = True

        'Changed PM_MEMORY_ALLOCATION 2004-07-27.
        'Note: no need to use Regex here.

        'Changed PM_NEWMASCOT2_FORMAT 2004-06-17
        'Dim result As Match = Regex.Match(mMascotResStr, "<DIV class=tooltip id=Q1>")
        Dim result As Match = _
          Regex.Match(mMascotResStr, "<DIV class=tooltip id=Q")

        'temp!!!!!!!!!!!!!
        'PILInputOutput.pushToFile("C:\_tempMascotRes.txt", mMascotResStr)

        If Not result.Success Then
            'Changed PM_REFACTOR 2004-12-13
            'mChunkedParsingInfo.toolTipErrMsg =
            '  "No queries with tool tip information"
            Me.addParseError( _
              "No queries with tool tip information. " & _
              "Possible reasons: " & ControlChars.NewLine & _
              ControlChars.NewLine & _
              "1. Mascot result file was saved from " & _
              "FireFox, Opera, Internet Exploiter 7, Netscape or " & _
              "some other Web-browser that " & _
              "does not save in the same way as " & _
              "Internet Exploiter 6 (or earlier) does. " & _
              "Convert the result file using a suitable tool or " & _
              "use Internet Exploiter to save the result file." & _
              ControlChars.NewLine & _
              ControlChars.NewLine & _
              "2. The Mascot result was not formatted as ""Peptide View"". " & _
              "E.g. it was saved from the initial result page, ""XYZ"".   " _
              )

            'Changed PM_CODEMARKER 2007-08-24. Test this dialog text...

            mChunkedParsingInfo.majorState = parsingPhaseEnum.enumParsingError
            noErrors = False
        End If

        If noErrors Then
            Dim startPosition2 As Integer = result.Index

            'Changed PM_MEMORY_ALLOCATION 2004-07-27
            mCurrentIndexIntoHTML = startPosition2

            'Version 1.8 of Mascot:
            'Sample line, single line but line endings
            'added here: <DIV class=tooltip id=Q72>
            '<PRE>Top scoring peptide matches to query 72<BR>
            '    (Elution from: 31.8 to 31.8   period: 0  
            '  experiment: 2 cycles:  1  )<BR>
            '  Score greater than 35 indicates identity<BR>
            '  <I>Status bar shows all hits for this peptide</I><BR> <BR>
            '  <B>Score   Delta  Hit             Protein   Peptide</B><BR>
            '   47.8    0.04  102   MAL14.711c,1396.t00  IIEIYK<BR>
            '   47.8    0.04   8     IPI:IPI00024102.1  LIELYK<BR>
            '  47.8    0.04  224        PFM0195w,cyc-4  ILELYK<BR>
            '  44.7    0.03  159+          1399.t00058  ILKNYK<BR>
            '  44.7    0.07  246     IPI:IPI00000887.1  LLQNYK<BR>
            '  44.7    0.07  201    MAL4P1.32,PFD0160w  IIQNYK<BR>
            '  32.0    0.03  284              PFM0720w  LINKYK<BR>
            '  32.0    0.03  209   MAL14.220,1396.t005  ILNKYK<BR>
            '  32.0    0.03  465    MAL7P1.82,PFG0670w  IIKYNK<BR>
            '  32.0    0.04  182   MAL3P3.3,PFC0335c,P  IIEYLK</PRE></DIV>
            '
            'Sample empty line, single line but line endings
            'added here: <DIV class=tooltip id=Q1>
            '  <PRE>Top scoring peptide matches to query 1<BR>
            '    (Elution from: 0.47 to 0.47   period: 0
            '  experiment: 1 cycles:  1  )<BR>
            '  Score greater than 36 indicates identity<BR>
            '  <I>Status bar shows all hits for this peptide</I><BR>
            '   <BR><B>Score   Delta  Hit             Protein   Peptide</B></PRE></DIV>

            'Version 1.9 of Mascot:
            ' <DIV class=tooltip id=Q181>
            ' <TABLE cellSpacing=0 cellPadding=2 bgColor=#0000ff border=0>
            '   <TBODY>
            '   <TR>
            '     <TD>
            '       <TABLE cellSpacing=0 cellPadding=5 bgColor=#ffffcc border=0>
            '         <TBODY>
            '         <TR>
            '           <TD><PRE>Top scoring peptide matches to query 
            '           181<BR>  (Elution from: 57.93 to 57.93   
            '           period: 0   experiment: 1 cycles:  1  
            '           )<BR>Score greater than 31 indicates 
            '           homology<BR>Score greater than 37 indicates 
            '           identity<BR><I>Status bar shows all hits for 
            '           this peptide</I><BR> <BR><B>Score   Delta  Hit                  
            '           Protein   Peptide</B><BR> 20.0    0.04  230                
            '           IPI00167260  FSIPSPTFSK<BR> 17.1    0.10  411                
            '           IPI00010480  SFLPSGSEMR<BR> 17.1    0.13  413                
            '           IPI00217812  
            '           <U>M</U>SVNMDELR</PRE></TD></TR></TBODY></TABL
            '           E></TD></TR></TBODY></TABLE></DIV>

            'Version 2.xx of Mascot, installed 2004-06, reformatted here (the first query is NOT 1):
            '<DIV class=tooltip id=Q177>
            '<TABLE cellSpacing=0 cellPadding=2 bgColor=#0000ff border=0>
            '  <TBODY>
            '  <TR>
            '    <TD>
            '      <TABLE cellSpacing=0 cellPadding=5 bgColor=#ffffcc border=0>
            '        <TBODY>
            '        <TR>
            '          <TD><TT>Top scoring peptide matches to query 177<BR>Elution from: 
            '            10.2166666666667 to 10.2166666666667 period: 0 experiment: 1 cycles: 
            '            1 FinneganScanNumber: 613<BR>Score greater than 25 indicates 
            '            identity<BR><I>Status bar shows all hits for this peptide</I>
            '</TT><PRE><B>Score   Delta  Hit  Protein     Peptide</B>
            '<BR> 24.8    0.00   12  gi|33413750 LEPSR<BR>
            ' 10.8    0.00                   ELSPR<BR>
            ' 10.8    0.00                   ELPSR<BR>
            '  9.0   -0.00                   ITDPR<BR>
            '  9.0   -0.00                   LTDPR<BR>
            '  6.7    0.00                   AAELR<BR>
            '  5.4   -0.00                   TI<U>N</U>PR<BR>
            '  5.4   -0.00                   TLDPR<BR>
            '  4.5    0.00                   GQVLQ</PRE></TD>
            '</TR></TBODY></TABLE></TD></TR></TBODY></TABLE></DIV>

            'We can extract from a particular query number (they should all
            'be there in order) to  the end of line.
            'Note: we do not need to remove at the end because the
            'tool-tips are at the end of the file.

            'Changed PM_MEMORY_ALLOCATION 2004-07-27. Avoid copying.
            'Dim ttStr2 As String = mMascotResStr.Remove(0, startPosition3)

            'Changed PM_MEMORY_PROBLEM 2004-04-13
            ''Remove new-line characters
            ''Dim ttStr4 As String
            'If True Then

            '    If True Then
            '        ttStr2 = ttStr2.Replace(Chr(10), "")
            '        ttStr4 = ttStr2.Replace(Chr(13), "")
            '    Else
            '        'Note: way too slow and demanding on dynamic memory; in an example
            '        '      the array contained 189873 elements!
            '        Dim temp1Arr As String() = ttStr2.Split(New Char() {Chr(10)})
            '        Dim temp1Str As String = Join(temp1Arr, " ")
            '        Dim len2 As Integer = temp1Str.Length()
            '        Dim temp2Arr As String() = temp1Str.Split(New Char() {Chr(13)})
            '        ttStr4 = Join(temp2Arr, " ")

            '        'Changed PM_MEMORY_PROBLEM 2004-04-05
            '        temp1Arr.Clear(temp1Arr, 0, temp1Arr.Length() - 1)
            '        temp2Arr.Clear(temp2Arr, 0, temp2Arr.Length() - 1)
            '    End If

            '    'Test only
            '    Dim len1 As Integer = ttStr2.Length()
            '    Dim len3 As Integer = ttStr4.Length()

            '    Dim peter9 As Integer = 9
            'End If

            'Changed PM_MEMORY_ALLOCATION 2004-07-27
            ' 'Changed PM_MEMORY_ALLOCATION 2004-07-27
            ' 'Cut out the trailing HTML, "</BODY></HTML>".
            ' Dim ttStr As String
            ' If True Then
            '     '   "</BODY>"
            '     'Changed PM_MEMORY_PROBLEM 2004-04-13
            '     'Dim temp4Arr As String() = Regex.Split(ttStr4, "</BODY>")
            '     Dim len2 As Integer = ttStr2.Length
            '     Dim temp4Arr As String() = Regex.Split(ttStr2, "</BODY>")
            '     ttStr = temp4Arr(0)
            ' 
            '     'Changed PM_MEMORY_PROBLEM 2004-04-05
            '     temp4Arr.Clear(temp4Arr, 0, temp4Arr.Length() - 1)
            ' End If
            Dim endPosition As Integer = mMascotResStr.LastIndexOf("</BODY>")

            'Test only
            If False Then
                Dim startStr As String = mMascotResStr.Substring(startPosition2, 10)
                Dim endStr As String = mMascotResStr.Substring(endPosition, 10)
                Dim peter41 As Integer = 41
            End If

            'Changed PM_MEMORY_ALLOCATION 2004-07-27
            'We are not concerned with CPU efficiency right now, only memory allocations.
            Dim items As Integer = 0
            If True Then
                Dim curIndex As Integer = startPosition2
                Dim done As Boolean = False

                Dim prevIndex As Integer = curIndex 'For debugging only
                Dim substr As String

                While Not done
                    Dim newIndex As Integer = _
                      mMascotResStr.IndexOf("</DIV>", curIndex)
                    If newIndex < 0 Then
                        done = True
                    Else
                        If False Then
                            Dim distance As Integer = newIndex - prevIndex
                            substr = _
                              mMascotResStr.Substring(prevIndex, distance)
                        End If
                        curIndex = newIndex + 1 'Go past current.
                        prevIndex = newIndex
                        items += 1
                    End If
                End While
            End If

            'Changed PM_MEMORY_ALLOCATION 2004-07-27
            ''Split by "</DIV>"
            'mChunkedParsingInfo.toolTipItems = Regex.Split(ttStr, "</DIV>")

            'Changed PM_MEMORY_ALLOCATION 2004-07-27
            'mChunkedParsingInfo.toolTips = _
            '  mChunkedParsingInfo.toolTipItems.GetLength(0)
            mChunkedParsingInfo.toolTips = items

            '1. The last line may be empty. It is because there is no
            '   record after the last "</DIV>".
            '2. Update for Mascot 2.0, 2004-03: it may
            '   contain this string:
            '  "<!-- 5 seconds --><!-- 10 seconds --><!-- 15 seconds -->"

            'Changed PM_MEMORY_ALLOCATION 2004-07-27. Should no longer be necessary
            ' Dim lastItem As String = _
            '   mChunkedParsingInfo.toolTipItems(mChunkedParsingInfo.toolTips - 1)
            ' Dim ttStrArr7 As String() = Regex.Split(lastItem, "<DIV") 'Note: very 
            ' '  short, only used for the adjustment below.
            ' 
            ' 'If lastItem.Length < 5 Then 'then its not real
            ' '.Length: will be 1 unless the very last in the string was </DIV> (?).
            ' If ttStrArr7.Length < 2 Then 'then its not real
            '     mChunkedParsingInfo.toolTips -= 1
            ' End If

            ReDim mTtQueryArr(mChunkedParsingInfo.toolTips - 1) 'Prepare for 
            '  subsequent filling in.
        End If 'No errors

        'Dim timeSliceSecs As Double = 0.3
        mChunkedParsingInfo.chunkerParsing.Init( _
          0, mChunkedParsingInfo.toolTips - 1, True)
    End Sub 'tooltipParsingInit


    'Changed PM_PARSE_CHUNKED 2004-04-07
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '*    Helper function                                                       *
    '****************************************************************************
    Private Sub proteinParsingInit()

        mRawFiles = mMultipleRawFilesHandling.getRawFiles()

        'Changed PM_MULTIPLE_FINNEGAN_TROUBLE_EXTREME_SLOWDOWN 2004-01-06
        '
        'Patch .startElutionTime from .spectrumNumber.
        '  We wait until now to do the patching because it is very,
        '  very expensive to change between raw files - opening/closing...
        If Not mRawFiles Is Nothing Then 'There may not be any raw file refs in
            '  the period fields....
            'Outer loop: one raw file at a time
            Dim lastIndex As Integer = mRawFiles.Length - 1
            Dim j As Integer
            For j = 0 To lastIndex
                Dim curTag As Integer = mRawFiles(j).tag2

                Dim i As Integer
                Dim lastIndex2 As Integer = mChunkedParsingInfo.toolTips - 1
                For i = 0 To lastIndex2
                    Dim curItem3 As TTQueryStruct = mTtQueryArr(i)
                    Dim rawFileRefNum As Integer = curItem3.qRawFileID
                    If rawFileRefNum = curTag Then
                        Dim spectrumNum As Integer = curItem3.spectrNumb
                        If spectrumNum > 0 Then 'This can be false if spectrum ..

                            'Note: fields spectrum number and startElutionTime
                            '      were filled in during parsing of the tooltips.
                            'Changed PM_RAW2MSM_COMPATIBLE 2008-04-01
                            'Trace.Assert(curItem3.startElutionTime > 0.0, _
                            '  "PIL ASSERT. Retention time is negative!. Spectrum number: " & _
                            '  spectrumNum & ". Raw file ID: " & rawFileRefNum & ".")
                            Trace.Assert(curItem3.startElutionTime > -0.0001, _
                              "PIL ASSERT. Retention time is negative!. Spectrum number: " & _
                              spectrumNum & ". Raw file ID: " & rawFileRefNum & ".")

                            'Number is not in the tooltip, e.g. for QSTAR data.
                            Dim startElutionTime As Double = 4444.4444444
                            Try
                                Dim retMinutes As Double = _
                                  mMultipleRawFilesHandling.MaybeToBeChanged_MSMSretentionTime( _
                                    spectrumNum, curItem3.experimentNumber, rawFileRefNum) / 60.0
                                startElutionTime = retMinutes

                            Catch exceptionObject As Exception
                                Dim extraErrMsg As String = _
                                  "Error: " & exceptionObject.ToString
                                MsgBox("Problem accessing the raw data file. The raw file mode (in Tools/Options) may not match the raw data file type of the raw data file in use..... " & _
                                " Extra info: " & ControlChars.NewLine & ControlChars.NewLine & extraErrMsg)
                                Exit Sub
                            End Try

                            mTtQueryArr(i).startElutionTime = startElutionTime 'Write-back
                        End If
                    End If
                Next
                Dim peter3 As Integer = 3 'Through one raw file.
            Next
        Else
            'Changed PM_NOMULTIPLE_ASSERT 2004-01-28
            Trace.Assert(False, "PIL ASSERT. This should never happen...")
        End If

        'Go through entire web page and locate all protein hit headers (1000)
        'this takes very little time (can't measure with a normal datetime call).
        '
        'Changed PM_MASCOT2_SUPPORT 2004-03-01
        'Start of a hit: <A name=Hit1><B>1.</B></A> where 1 is the protein hit number 1-1000
        '  group 1 will be the protein hit number.
        'Update for Mascot 2:
        '  The bold tag is now missing, as in:
        '    "<A name=Hit7>7.</A>&n".
        '
        'theMatchCol = Regex.Matches(mMascotResStr, "<A name=Hit\d+><B>(\d+).</B></A>")
        mChunkedParsingInfo.matchCol = Regex.Matches(mMascotResStr, _
          "<A name=Hit\d+>[^0-9]*(\d+)[^A]+</A>")

        Dim numProteinsParsed As Integer = mChunkedParsingInfo.matchCol.Count
        mChunkedParsingInfo.numProteinsParsed = numProteinsParsed
        Trace.Assert(numProteinsParsed > 0, _
          "PIL ASSERT. No proteins detected!. Perhaps it is a problem with the format of the Mascot result file.")

        mChunkedParsingInfo.proteinsInTable = 0

        'Changed PM_EVENMORE_GENERALISED_QUANTMODES 2005-04-08. Not needed anymore...
        ' 'Changed PM_EVENMORE_GENERALISED_QUANTMODES 2005-04-08
        ' 'Dim quantitationModesObject As QuantitationModes = _
        ' '  mApplication.getQuantitationModesObject()
        ' 'Dim curQuantMode As quantitationModeStructure = _
        ' '  quantitationModesObject.getQuantitationMode( _
        ' '    mChunkedParsingInfo.options.quantModeCode)
        ' Dim quantitationModesObject As QuantitationModes_moreGeneral = _
        '   mApplication.getQuantModes()
        ' Dim curQuantMode As generalisedQuantModeStructure = _
        '   quantitationModesObject.getQuantitationMode( _
        '     mChunkedParsingInfo.options.quantModeCode)
        ' 
        ' 'Changed PM_REFACTOR_INSERT_NATIVEPEPTIDE 2003-10-15
        ' Dim theQuantValues As massSpectrometryBase.quantValuesStructure
        ' 'The derived information depends only on the quantitation mode, not
        ' 'on modifications (identified by Mascot) for a particular peptide.
        ' massSpectrometryBase.FindLCpeaks.derivedValuesFromQuantitationMode( _
        '   curQuantMode, quantitationModesObject, theQuantValues)
        ' mChunkedParsingInfo.quantValues = theQuantValues

        mChunkedParsingInfo.firstHitNumber = -1

        'Dim timeSliceSecs As Double = 0.6
        mChunkedParsingInfo.chunkerParsing.Init( _
          0, numProteinsParsed - 1, True)
    End Sub 'proteinParsingInit


    'Changed PM_REFACTOR 2004-07-27
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Private Sub chunk_FileRead( _
      ByRef aReadBuffer() As Char, _
      ByVal aBufferSize As Integer, _
      ByRef aEOLcharacters() As Char, _
      ByRef anOutProcessedCount As Integer, _
      ByRef anOutEstimatedEndCount As Integer, _
      ByRef anOutStats As parsingStatsStructure, _
      ByRef anOutPhaseTransition As Boolean)

        Dim doneWithFile As Boolean = False
        Dim done As Boolean = False
        Dim readChunkSize As Integer = 0
        While (Not mChunkedParsingInfo.chunkerParsing.timeIsUp()) And _
               Not done

            Dim actualBytes As Integer
            actualBytes = mChunkedParsingInfo.inputStreamReader.Read( _
              aReadBuffer, 0, aBufferSize)
            mChunkedParsingInfo.rawBytesRead += actualBytes

            Dim bytesToRemove As Integer = aBufferSize - actualBytes
            Dim bufStr As String = aReadBuffer

            If False Then 'Test only, slows down things
                Dim enc As System.Text.UTF8Encoding = _
                  New System.Text.UTF8Encoding

                Dim ab As Byte() = enc.GetBytes(bufStr)
                'Dim utf8Count As Integer = enc.GetChars(ab, 0, BUFSIZE)
                Dim utf8Count As Integer = _
                  enc.GetCharCount(ab, 0, aBufferSize)
                If utf8Count <> aBufferSize Then
                    Dim peter100 As Integer = aBufferSize
                End If
            End If

            If bytesToRemove > 0 Then
                'Should only happen for the very last part
                'of the file.
                bufStr = bufStr.Remove(actualBytes, bytesToRemove)
            Else
            End If

            'Changed PM_MEMORY_ALLOCATION 2004-07-26
            'Single character filtering.
            'Append every line to .fileContent instead of lots
            'of copying and thus strain on garbage collection.
            Dim bytesAfterFiltering As Integer = 0
            Dim done2 As Boolean = False
            Dim prevIndex As Integer = 0
            Dim len As Integer = -1
            While Not done2
                Dim index As Integer = _
                  bufStr.IndexOfAny(aEOLcharacters, prevIndex)
                If index < 0 Then
                    index = bufStr.Length
                    done2 = True
                End If
                len = index - prevIndex
                If len > 0 Then
                    mChunkedParsingInfo.fileContent.Append( _
                      bufStr, prevIndex, len)
                    bytesAfterFiltering += len
                Else
                    Dim peter9 As Integer = 9
                End If
                prevIndex = index + 1 '1 to jump over EOL char.
            End While

            'Changed PM_MEMORY_ALLOCATION 2004-07-26
            bufStr = Nothing

            'Old. Delete at any time.
            ' 'Single character filtering.
            ' 'Later:  -Replace(Chr(10), "")  instead.
            ' 'Changed PM_PARSE_CHUNKED 2004-04-13
            ' 'bufStr = bufStr.Replace(vbLf, " "c)
            ' 'bufStr = bufStr.Replace(vbCr, " "c)
            ' bufStr = bufStr.Replace(Chr(10), "")
            ' bufStr = bufStr.Replace(Chr(13), "")
            ' Dim bytesAfterFiltering As Integer = bufStr.Length
            ' If actualBytes <> bytesAfterFiltering Then
            '     Dim peter9 As Integer = 9
            ' End If
            ' 'Changed PM_MEMORY_PROBLEM 2004-04-14
            ' 'bitForChunk.Append(bufStr, 0, bytesAfterFiltering)
            ' mChunkedParsingInfo.fileContent.Append( _
            '   bufStr, 0, bytesAfterFiltering)

            readChunkSize += bytesAfterFiltering

            If mChunkedParsingInfo.rawBytesRead >= _
              mChunkedParsingInfo.bytesInResultFile Or _
              actualBytes = 0 Then 'For some reason we are missing 2 bytes in 
                'the file.....

                doneWithFile = True
                done = True
            End If
        End While

        'Changed PM_MEMORY_PROBLEM 2004-04-14
        'anOutStats.bytesReadInThisChunk = bitForChunk.Length
        anOutStats.bytesReadInThisChunk = readChunkSize
        'mMascotResStr &= bitForChunk.ToString

        'Changed PM_MEMORY_ALLOCATION 2004-07-26. Disabled....
        ''Changed PM_MEMORY_PROBLEM 2004-04-14
        If False Then
            Dim chunksize As Integer = readChunkSize
            Dim totalSize As Integer = _
              mChunkedParsingInfo.fileContent.Length
            Dim filesize As Integer = _
              CInt(mChunkedParsingInfo.bytesInResultFile)
            Dim msgStr As String = _
              chunksize & vbTab & totalSize & vbTab & filesize
            mLogger.timeLog(msgStr)
        End If

        If doneWithFile Then
            'Changed PM_MEMORY_ALLOCATION_TEST 2004-07-26
            quantApplication.stopNow("Done reading file", False)

            'Changed PM_MEMORY_ALLOCATION 2004-07-27
            ''Changed PM_MEMORY_PROBLEM 2004-04-14
            'mMascotResStr &= mChunkedParsingInfo.fileContent.ToString
            mMascotResStr = mChunkedParsingInfo.fileContent.ToString
            Dim strLen As Integer = mMascotResStr.Length

            'Clean up
            mChunkedParsingInfo.inputStreamReader.Close()
            mChunkedParsingInfo.inputFileStream.Close()
            mChunkedParsingInfo.fileContent = Nothing

            'Changed PM_MEMORY_ALLOCATION 2004-08-06
            Dim memDiffMB As Double
            Dim tickTimeSecs As Double
            quantApplication.GarbageCollect(mLogger, memDiffMB, tickTimeSecs)

            'Changed PM_MEMORY_PROBLEM 2004-04-14
            'mLogger.readOutTimeLog()

            'State change
            anOutPhaseTransition = True
            mChunkedParsingInfo.majorState = _
              parsingPhaseEnum.enumParsingToolTips

            'Set up for tooltip.
            'Note: may change state if there is an error
            Me.tooltipParsingInit( _
              mChunkedParsingInfo.options, _
              mChunkedParsingInfo.rawFilePath, _
              mChunkedParsingInfo.sampleNum)

            anOutProcessedCount = 0 'Because we have already changed 
            '  state and need to report 0 % progress to not confuse
            '  the client.
            anOutEstimatedEndCount = 1

            'Changed PM_MEMORY_ALLOCATION 2004-07-27
            quantApplication.stopNow("tooltipParsingInit() completed", False)
        Else
            'In this phase cur count is number of bytes read from
            'the Mascot HTML result file.
            anOutProcessedCount = mChunkedParsingInfo.rawBytesRead

            'Would not work for 64 bit.
            anOutEstimatedEndCount = _
              CInt(mChunkedParsingInfo.bytesInResultFile)
        End If
    End Sub 'chunk_FileRead


    'Changed PM_REFACTOR 2004-12-13
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Private Sub parseTooltipError( _
      ByRef anInErrorMsg As String, ByRef anInOutNoProblemFlag As Boolean, _
      ByRef anAccumErrString As String)

        Dim errStr As String = anInErrorMsg & ControlChars.NewLine
        Me.addParseError(errStr)
        anInOutNoProblemFlag = False

        'Changed PM_BETTER_PARSEERROR_MESSAGE 2007-08-02
        If anAccumErrString Is Nothing Then
            anAccumErrString = ""
        Else
            Dim peter2 As Integer = 2 'This happens only if there is more
            '  than one parse error for a peptide.
        End If
        anAccumErrString &= errStr

    End Sub 'parseTooltipError


    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Private Sub chunk_ParsingToolTips( _
        ByRef anOutProcessedCount As Integer, _
        ByRef anOutEstimatedEndCount As Integer, _
        ByRef anOutPhaseTransition As Boolean _
        )

        Dim done As Boolean = False
        Dim TTQuery As TTQueryStruct
        Dim i As Integer = 0

        While (Not mChunkedParsingInfo.chunkerParsing.timeIsUp()) And _
               Not done

            i = mChunkedParsingInfo.chunkerParsing.currentNumber()

            Dim errorsForPeptide As String = Nothing 'Only set if there
            '  as an error.

            'Changed PM_MEMORY_ALLOCATION 2004-07-27
            Dim newIndex As Integer = _
              mMascotResStr.IndexOf("</DIV>", mCurrentIndexIntoHTML + 1)
            Trace.Assert(newIndex >= 0, "PIL ASSERT. newIndex is negative.")
            Dim distance As Integer = newIndex - mCurrentIndexIntoHTML
            Dim tooltipStr As String = _
              mMascotResStr.Substring(mCurrentIndexIntoHTML, distance)
            mCurrentIndexIntoHTML = newIndex

            Dim noProblem As Boolean = True

            'Don't forget to initalize TTQuery every time around.
            With TTQuery
                .cycle = 0
                .endElutionTime = 0
                .experimentNumber = 0
                .modLocSeq1 = 0
                .modLocSeq2 = 0
                .seq1Unique = False
                .seq2Unique = False
                .period2 = 0
                .queryNo = 0
                .score1 = 0
                .score2 = 0

                'Changed PM_STRING_CLEANUP 2004-12-14
                '.seq1 = ""
                '.seq2 = ""
                .seq1 = Nothing
                .seq2 = Nothing

                .startElutionTime = 0.0
            End With

            'Changed PM_MEMORY_ALLOCATION 2004-07-27
            'Dim str2 As String = mChunkedParsingInfo.toolTipItems(i)

            'Changed PM_MEMORY_ALLOCATION 2004-07-27
            'Changed PM_MASCOT2_SUPPORT 2004-03-01
            'Dim str As String
            'If False Then
            '    'Also split by <DIV> to eliminate things outside <DIV></DIV>, e.g.
            '    '  "<!--  xx seconds>" at the very end.
            '    Dim ttStrArr6 As String() = Regex.Split(str2, "<DIV")
            '    str = ttStrArr6(1) 'Last part.
            'Else
            '    'Old.
            '    str = str2
            'End If

            'First extract the query number to see if everything is consistent
            'peptide matches to query 72<BR>.
            Dim result As Match = Regex.Match(tooltipStr, _
              "peptide matches to query\s+([0-9]+)<BR>")

            'Changed PM_MEMORY_ALLOCATION 2004-08-02
            'Dim matchStr As String

            If result.Success Then
                'Changed PM_MEMORY_ALLOCATION 2004-08-02
                ''Changed PM_MEMORY_ALLOCATION 2004-07-28
                Dim queryNoStr As String = result.Groups(1).Value

                If IsNumeric(queryNoStr) Then
                    TTQuery.queryNo = CInt(queryNoStr)
                Else
                    'Changed PM_REFACTOR 2004-12-13
                    'noProblem = False
                    'mChunkedParsingInfo.numToolTipParseErrors += 1
                    'mChunkedParsingInfo.toolTipErrMsg &= _
                    '  "Incorrect query number" & vbCrLf
                    parseTooltipError( _
                      "Incorrect query number (not numeric): " & queryNoStr, _
                      noProblem, errorsForPeptide)
                End If
                queryNoStr = Nothing
            Else
                'Changed PM_REFACTOR 2004-12-13
                'noProblem = False
                'mChunkedParsingInfo.toolTipErrMsg &= "no query number" & vbCrLf
                'mChunkedParsingInfo.numToolTipParseErrors += 1
                parseTooltipError( _
                  "Incorrect query number. Could not be detected in: """ & _
                  tooltipStr & """", noProblem, errorsForPeptide)
            End If

            'Changed PM_NEWMASCOT2_FORMAT 2004-06-17. Disabled as the
            'sequence of query numbers is not consequetive for
            'Mascot 2.xx. It can be e.g. Q177, Q289, Q290, Q363,
            '  Q369, Q370, Q377, Q391, .... Q830, Q833, Q853.
            ''Ckeck it we are generally in register.
            'If Not theTTQuery.queryNo - 1 = i Then
            '    mChunkedParsingInfo.toolTipErrMsg &= "Query number wrong" & vbCrLf
            '    noProblem = False
            '    mChunkedParsingInfo.numToolTipParseErrors += 1
            'End If

            If True Then
                'Changed PM_FINNEGAN_RETENTION_TIME 2003-11-18
                'This will only be in some files, not all.
                Dim spectrumNum As Integer = -1

                'Changed PM_TITLELINEPARSING 2007-06-14
                ''Changed PM_MASCOT2_SUPPORT_FINNEGANSPECTRUMNUMBER_TROUBLE 2004-03-16
                ''result = Regex.Match(str, "FinneganScanNumber:\s+(.+)\)")
                'result = Regex.Match(tooltipStr, "FinneganScanNumber:\D*(\d+)\D+")
                result = Regex.Match( _
                  tooltipStr, _
                  mTITLElineParsing.scanNumber3.regularExpression)

                If result.Success Then
                    spectrumNum = CInt(result.Groups(1).Value)

                    If spectrumNum = 75 Then
                        Dim peter2 As Integer = 2
                    End If

                End If
                TTQuery.spectrNumb = spectrumNum
            End If

            'Changed PM_PRECURSOR_INTENSITY 2005-09-08
            If True Then
                Dim precIntensity As Double = -10.0
                result = Regex.Match(tooltipStr, "precIntensity:\s+(\S+)\s+")
                If result.Success Then
                    precIntensity = CDbl(result.Groups(1).Value)
                End If
                TTQuery.precursorIntensity = precIntensity
            End If

            ''Elution from: 31.8 to 31.8
            ''Changed PM_NEWMASCOT2_FORMAT 2004-06-17. Space vs. white space.
            ''result = Regex.Match(str, "Elution from: ([.0-9]+)\s+to")
            'result = Regex.Match(tooltipStr, "Elution from:\s+([.0-9]+)\s+to")
            result = Regex.Match( _
              tooltipStr, _
              mTITLElineParsing.retentionTime3.regularExpression)

            If result.Success Then
                'Changed PM_MEMORY_ALLOCATION 2004-07-28
                Dim startElutionTimeStr As String = result.Groups(1).Value

                If IsNumeric(startElutionTimeStr) Then
                    TTQuery.startElutionTime = CDbl(startElutionTimeStr)
                Else
                    'Changed PM_REFACTOR 2004-12-13
                    'mChunkedParsingInfo.toolTipErrMsg &= "Elution time wrong" & vbCrLf
                    'noProblem = False
                    'mChunkedParsingInfo.numToolTipParseErrors += 1
                    parseTooltipError("Elution time wrong", _
                      noProblem, errorsForPeptide)
                End If

                'Changed PM_MEMORY_ALLOCATION 2004-08-02
                startElutionTimeStr = Nothing
            Else
                'Changed PM_BETTER_PARSEERROR_MESSAGE 2007-08-02
                Dim extraInfo As String = _
                  "Parsing with rule """ & _
                  mTITLElineParsing.retentionTime3.regularExpression & _
                  """ for the following text did not find a match: " & _
                  tooltipStr

                parseTooltipError( _
                  "Elution time wrong. " & extraInfo, _
                  noProblem, errorsForPeptide)
            End If

            'Changed PM_SEVERALWIFFS_MARKER 2003-08-22

            Dim rawFileRefNum As Integer = -1
            If True Then
                'Changed PM_REFACTOR 2003-11-21
                'Dim periodValueString As String = ""
                'Dim rawFileNumberToUse As Integer

                'Changed PM_REFACTOR_TITLELINEPARSING 2007-06-08
                ''Changed PM_NOMULTIPLE_ASSERT 2004-01-28
                ' ''period: 0   experiment:
                ' ''result = Regex.Match(str, "period:\s+([0-9]+)\s+ex")
                ''result = Regex.Match(str, "period:\s+(.+)\s+ex") 'Why
                ' ''  can periodString contain one or more spaces?? E.g. "0 " Greedy match?
                'result = Regex.Match(tooltipStr, "period:\s+(\S+)\s+ex")
                result = Regex.Match( _
                  tooltipStr, _
                  mTITLElineParsing.rawFile3.regularExpression)

                'Changed PM_MASCOTDLL_11_DETECTION 2005-12-15
                If result.Length = 0 Then

                    'Changed PM_READPARSINGRULES 2007-11-23
                    'Dim msgStr As String = _
                    '  "MSQuant could not extract information from the " & _
                    '  "tooltip, query number " & TTQuery.queryNo & ". " & _
                    '  "The ""period"" field was not present (case-sensitive) " & _
                    '  "and/or does not preceed the ""experiment"" field " & _
                    '  "(case-sensitive). " & _
                    '  "For QSTAR/Sciex/Analyst the most likely reason for " & _
                    '  "this is that Mascot.dll for QS 1.1 was used for " & _
                    '  "generating the input file for the Mascot " & _
                    '  "search (the .mgf/.tmp file). " & _
                    '  "Do the Mascot search with a mgf (or tmp) file in a format " & _
                    '  "that MSQuant will later understand " & _
                    '  "(e.g. using the QSbroken2QSclassic script)." & _
                    '  ControlChars.NewLine & _
                    '  ControlChars.NewLine & _
                    '  "Extra information, regular expression: " & _
                    '  mTITLElineParsing.rawFile3.regularExpression & _
                    '  ControlChars.NewLine & _
                    '  ControlChars.NewLine & _
                    '  "Extra information, input for the matching: " & _
                    '  ControlChars.NewLine & _
                    '  tooltipStr & _
                    '  ControlChars.NewLine & _
                    '  ""
                    Dim msgStr As String = _
                      "The rule """ & mTITLElineParsing.rawFile3.regularExpression & _
                      """ did not match anything in a tooltop item with this content: " & _
                      ControlChars.NewLine & _
                      ControlChars.NewLine & _
                      """" & tooltipStr & """" & _
                      ControlChars.NewLine & _
                      ControlChars.NewLine & _
                      "The XXX does not match the format of the tooltop information in the Mascot result file. " & _
                      "Select an appropriate MGF file generator (menu Tools/Options). "

                    'Use MsgBox() or parseTooltipError() ? MsgBox(), as
                    'parseTooltipError() does not display anything..
                    MsgBox(msgStr)

                    'Changed PM_ALMOSTINFINITELOOP_PERIODFIELD 2006-02-09
                    'Make sure we terminate parsing after just one detection
                    'of this problem.
                    mChunkedParsingInfo.majorState = _
                      parsingPhaseEnum.enumParsingError
                End If

                'Changed PM_MEMORY_ALLOCATION 2004-08-02
                'matchStr = result.Groups(1).Value
                Dim periodStr As String = result.Groups(1).Value
                If IsNumeric(periodStr) Then

                    'Changed PM_MEMORY_ALLOCATION 2004-07-28
                    'theTTQuery.period = CInt(result.Groups(1).Value)
                    TTQuery.period2 = CInt(periodStr)

                    'Changed PM_REFACTOR 2003-11-21
                    ''Changed PM_SEVERALWIFFS_BACKCOMPATIBILITY 2003-08-28
                    'rawFileNumberToUse = RAWFILEREF_NOTMULTIPLE
                    'periodValueString = "NO_MULTIPLE"
                Else
                    'OK, probably a raw file name...
                End If 'Numeric or embedded raw file name.

                If True Then
                    'Changed PM_REFACTOR 2003-11-21
                    ''Would be so much more compact in Perl!
                    'Dim rawFileRefNum As Integer = -1
                    'If anOutRawFileNames.Contains(periodValueString) Then 'What
                    '    '  is the difference between Contains and ContainsKey?.
                    '    rawFileRefNum = _
                    '      CInt(anOutRawFileNames(periodValueString))
                    'Else
                    '    anOutRawFileNames.Add(periodValueString, rawFileNumberToUse)
                    '    rawFileRefNum = rawFileNumberToUse
                    '    currentRawFileNumber += 1
                    'End If
                    rawFileRefNum = _
                      mMultipleRawFilesHandling.addPossibleFileName( _
                        periodStr, noProblem, _
                        mChunkedParsingInfo.numToolTipParseErrors2)
                    Trace.Assert(rawFileRefNum > 0, "PIL ASSERT. Bad raw file ID...")
                    TTQuery.qRawFileID = rawFileRefNum
                End If

                'Changed PM_MEMORY_ALLOCATION 2004-08-02
                periodStr = Nothing
            End If 'Field "Period"

            'Changed PM_REFACTOR_TITLELINEPARSING 2007-06-08
            ''Experiment: 2 cycles: 'this can also be experiments: 1 to 4 so
            ''we try twice.
            'result = Regex.Match(tooltipStr, "experiment:\s+([0-9]+)\s+cycles")
            result = Regex.Match( _
              tooltipStr, _
              mTITLElineParsing.experiment3.regularExpression)

            If result.Success Then
                Dim experimentNoStr As String = result.Groups(1).Value

                If IsNumeric(experimentNoStr) Then
                    TTQuery.experimentNumber = CInt(experimentNoStr)

                    'Changed PM_TITLELINEPARSING 2007-06-08. Needed for QS 1.1 or
                    '  later.
                    Dim offset As Integer = _
                      CInt(mTITLElineParsing.experiment3.offset) 'We need to
                    '  do rounding as it is specified as double.
                    '  Perhaps later: use field INTERNAL_offsetInt.

                    TTQuery.experimentNumber += offset
                Else
                    'Changed PM_REFACTOR 2004-12-13
                    'noProblem = False
                    'mChunkedParsingInfo.numToolTipParseErrors += 1
                    'mChunkedParsingInfo.toolTipErrMsg &= _
                    '  "Problem extracting tool tip (Experiment wrong)" & vbCrLf
                    parseTooltipError( _
                      "Problem extracting tool tip (Experiment wrong)", _
                      noProblem, errorsForPeptide)
                End If

                'Changed PM_CLRPROFILER_PROBLEMS 2004-07-28
                experimentNoStr = Nothing
            Else 'Try again with second syntax.
                result = Regex.Match(tooltipStr, _
                  "experiments:\s+([0-9]+)\s") 'we only take the first experiment
                If result.Success Then
                    'Changed PM_MEMORY_ALLOCATION 2004-08-02
                    ''Changed PM_MEMORY_ALLOCATION 2004-07-28
                    'matchStr = result.Groups(1).Value
                    Dim experimentNoStr As String = result.Groups(1).Value

                    If IsNumeric(experimentNoStr) Then
                        TTQuery.experimentNumber = CInt(experimentNoStr)
                    Else
                        'Changed PM_REFACTOR 2004-12-13
                        'noProblem = False
                        'mChunkedParsingInfo.numToolTipParseErrors += 1
                        'mChunkedParsingInfo.toolTipErrMsg &= _
                        '  "Problem extracting tool tip (Experiment wrong)" & _
                        '  vbCrLf
                        parseTooltipError( _
                          "Problem extracting tool tip (Experiment wrong)", _
                          noProblem, errorsForPeptide)
                    End If

                    'Changed PM_CLRPROFILER_PROBLEMS 2004-07-28
                    experimentNoStr = Nothing
                End If
            End If
            'cycles:  1  

            'Changed PM_TITLELINEPARSING 2007-06-11
            ''Changed PM_NO_TRAILLING_SPACE_REQUIREMENT 2005-09-26
            ''result = Regex.Match(tooltipStr, "cycles:\s+([0-9]+)\s+")
            'result = Regex.Match(tooltipStr, "cycles:\s+([0-9]+)[^0-9]+") 'E.g. "<BR>"
            ''  is right after the number.
            result = Regex.Match( _
              tooltipStr, _
              mTITLElineParsing.cycles3.regularExpression)

            'Changed PM_MEMORY_ALLOCATION 2004-08-02
            ''Changed PM_MEMORY_ALLOCATION 2004-07-28
            'matchStr = result.Groups(1).Value
            Dim cycleStr As String = result.Groups(1).Value

            If IsNumeric(cycleStr) Then
                TTQuery.cycle = CInt(cycleStr)
            Else
                'Changed PM_REFACTOR 2004-12-13
                'noProblem = False
                'mChunkedParsingInfo.numToolTipParseErrors += 1
                'mChunkedParsingInfo.toolTipErrMsg &= _
                '  "Problem extracting tool tip (Cycles wrong)" & vbCrLf
                parseTooltipError( _
                  "Problem extracting tool tip (Cycles wrong)", _
                  noProblem, errorsForPeptide)
            End If
            cycleStr = Nothing

            'Extract first and second sequence string and first and second
            'double score.
            'Peptide</B><BR> 47.8    0.04  102   MAL14.711c,1396.t00  IIEIYK<BR>
            '   47.8    0.04   8     IPI:IPI00024102.1  LIELYK<BR>
            'This will extract the score and the delta value if they
            'exist (don't exist if no pept matched)

            'First we shorten the string.
            Dim removeIndex As Integer = tooltipStr.IndexOf("Peptide</B>")
            Trace.Assert(removeIndex > 0, "Not found: Peptide</B>")
            Dim theStr3 As String = tooltipStr.Remove(0, removeIndex)

            'Changed PM_CLRPROFILER_PROBLEMS 2004-07-28
            ''Changed PM_MEMORY_ALLOCATION 2004-07-27
            'str = Nothing 'To have it garbage collected early - hopefully....

            'Individual table lines end with <BR> or with </PRE></DIV> for
            'the last one make trailing chars the same lenght (3 chars) so we
            'can remove them from the entries.
            'Doesn't do overlapping matches so it only gets every other
            'line. In this case line 0 and line 2.
            'Matches = Regex.Matches(str, "<BR>.+?(<BR|</P)")
            'To avoid the bug use look ahead assertions: (?=pattern) This
            'only avances to before pattern.
            Dim Matches As MatchCollection = _
              Regex.Matches(theStr3, "<BR>.+?(?=<BR>|</PR)")

            'Test only!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            ''Changed PM_MEMORY_ALLOCATION 2004-07-27
            'theStr3 = Nothing 'To have it garbage collected early - hopefully....

            Dim j As Integer
            Dim lastIndex As Integer = Math.Min(Matches.Count - 1, 1)
            For j = 0 To lastIndex 'We only extract
                'the first two peptides for now.
                Dim rowStr As String = Matches.Item(j).Groups(0).Value

                'Changed PM_MASCOT21 2005-06-12
                'For Mascot 2.1: for some unknown reason sometimes there are
                'two <BR><BR> - this would normally be shown an empty line; but
                'not in a pop-up! (at least not Internet Exploiter or Opera.).
                '
                'Rather than modifying the regular expressions we for now just
                'adjust to this reality: detect if it is present, cut
                'the <BR> tag out....
                'The double tag is not very frequent so this change should have
                'minimum impact.
                If rowStr.StartsWith("<BR><BR>") Then
                    rowStr = rowStr.Substring(4)
                End If

                'Remove trailing three chars which are either <BR> or </PR.
                'rowStr = rowStr.Remove(rowStr.Length - 5, 4)
                'Extract all words in this string. They will be score,
                'mass delta, number of occurances, accession number and
                'sequence string (possibly formated for location of modification. 
                'Match all 'words delimted between white spaces or
                'starting with '>' or ending with either '<B' or '</'.
                'This now costs a lot of time: anything simpler?
                'Matches1 = Regex.Matches(rowStr, "(>|\s)(\S+)(\s|(<BR|</PRE))")
                'match isolated words or the end of the string
                Dim Matches1 As MatchCollection = _
                  Regex.Matches(rowStr, "(>|\s)(\S+)(\s|$)")

                If Matches1.Count > 0 Then
                    'First the score. This should be item 0 and group 2.
                    Dim dummyStr1 As String = _
                      Matches1.Item(0).Groups(2).Value
                    If IsNumeric(dummyStr1) Then
                        If j = 0 Then
                            TTQuery.score1 = CDbl(dummyStr1)
                        End If

                        If j = 1 Then
                            TTQuery.score2 = CDbl(dummyStr1)
                        End If
                    Else
                        'Changed PM_REFACTOR 2004-12-13
                        'mChunkedParsingInfo.toolTipErrMsg &= _
                        '  "Couldn't extract scores" & vbCrLf
                        parseTooltipError("Couldn't extract scores", _
                          noProblem, errorsForPeptide)
                    End If

                    'Changed PM_MEMORY_ALLOCATION 2004-08-02
                    dummyStr1 = Nothing

                    '3rd is hit number but doesn't always exist. 
                    'We ask for count >3 because the last one will be
                    'the peptide sequence.
                    If Matches1.Count > 3 Then

                        'Changed PM_MEMORY_ALLOCATION 2004-08-02
                        'dummyStr = Matches1.Item(2).Groups(2).Value
                        Dim dummyStr2 As String = _
                          Matches1.Item(2).Groups(2).Value

                        If dummyStr2.IndexOf("+") > 0 Then 'This means that
                            'the sequence is not unique.
                            '    If IsNumeric(dummyStr2) Then
                            If j = 0 Then
                                TTQuery.seq1Unique = False
                            ElseIf j = 1 Then
                                TTQuery.seq2Unique = False ' CInt(dummyStr2)
                            End If
                        Else
                            If j = 0 Then
                                TTQuery.seq1Unique = True
                            ElseIf j = 1 Then
                                TTQuery.seq2Unique = True
                            End If
                        End If

                        'Changed PM_MEMORY_ALLOCATION 2004-08-02
                        dummyStr2 = Nothing
                    End If

                    'We look at the last match so that there is no
                    'problem if the accession number has white spaces or is
                    'missing (alltogether).

                    'Note:
                    '  Mascot 2.xx:
                    '    Peptide</B><BR> 24.8    0.00   12  gi|33413750 LEPSR
                    '  It seems we pick the wrong column, dummyStr gets the
                    '  accession number string, gi|33413750 in this case.

                    'Changed PM_STRING_CLEANUP 2004-12-14
                    If False Then 'No need to do this if we are not going to use
                        '  them anyway.
                        'Changed PM_MEMORY_ALLOCATION 2004-08-02
                        'dummyStr = Matches1.Item(Matches1.Count - 1).Groups(2).Value
                        Dim dummyStr3 As String = _
                          Matches1.Item(Matches1.Count - 1).Groups(2).Value
                        If j = 0 Then
                            TTQuery.seq1 = dummyStr3
                        End If

                        If j = 1 Then
                            TTQuery.seq2 = dummyStr3
                        End If

                        'See if at least one modifications.
                        If j = 0 Then
                            If TTQuery.seq1.IndexOf("<") >= 0 Then
                                TTQuery.modLocSeq1 = TTQuery.seq1.IndexOf("<")
                            End If
                        ElseIf j = 1 Then
                            If TTQuery.seq1.IndexOf("<") >= 0 Then
                                TTQuery.modLocSeq1 = TTQuery.seq1.IndexOf("<")
                            End If
                        End If

                        'Changed PM_MEMORY_ALLOCATION 2004-08-02
                        dummyStr3 = Nothing
                    End If
                End If
            Next j

            mTtQueryArr(i) = TTQuery
            If Not noProblem Then

                'Only display the first few...
                Dim limit As Integer = 10
                If mChunkedParsingInfo.numToolTipParseErrors2 < limit Then
                    Dim msgStr As String = _
                      "Problem extracting information from the tooltip " & _
                      "section of the Mascot result file for query " & _
                      TTQuery.queryNo & ". Extra information: " & _
                      ControlChars.NewLine & ControlChars.NewLine & _
                      errorsForPeptide
                    MsgBox(msgStr)
                Else
                    If mChunkedParsingInfo.numToolTipParseErrors2 = limit Then
                        MsgBox( _
                          "The rest of the tooltip parse errors will " & _
                          "not be displayed...")
                    Else
                        'Be silent
                        Dim peter2 As Integer = 2
                    End If

                End If
            End If
        End While 'Going through tooltip list

        'Dim ToolTipExtrErrors As String() = _
        '  Me.ParseToolTips(mMultipleRawFilesHandling)

        If mChunkedParsingInfo.chunkerParsing.jobFinished() Then

            'Changed PM_MEMORY_ALLOCATION 2004-07-27
            quantApplication.stopNow("Done parsing tooltips", False)

            'Changed PM_MEMORY_ALLOCATION 2004-08-06
            Dim memDiffMB As Double
            Dim tickTimeSecs As Double
            quantApplication.GarbageCollect(mLogger, memDiffMB, tickTimeSecs)

            If mChunkedParsingInfo.numToolTipParseErrors2 = 0 Then
                mChunkedParsingInfo.majorState = _
                  parsingPhaseEnum.enumParsingProteins

                Me.proteinParsingInit() 'This is assumed to not take too long
                '  time, otherwise it will need to be chunked.
            Else
                mChunkedParsingInfo.majorState = _
                  parsingPhaseEnum.enumParsingError
            End If

            'Changed PM_MEMORY_ALLOCATION 2004-08-06
            Dim memDiffMB2 As Double
            Dim tickTimeSecs2 As Double
            quantApplication.GarbageCollect(mLogger, memDiffMB2, tickTimeSecs2)

            'Changed PM_MISSING_STATE_CHANGE_INDICATION 2004-07-30
            anOutPhaseTransition = True

            anOutProcessedCount = 0 'Because we have already changed state 
            '  and need to report0 % progress to not confuse the client.
            anOutEstimatedEndCount = 1
        Else
            anOutProcessedCount = i + 1 '1 because i is zero-based
            anOutEstimatedEndCount = mChunkedParsingInfo.toolTips
        End If
    End Sub 'chunk_ParsingToolTips


    'Better name?
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Private Sub postProteinParsing2()
        'Changed PM_CHECK_ALL_AAS_MODIFIED 2003-12-03
        Dim nonMatch As Integer = _
          mMultModCounter.nonMatchingAAsToModificationCountFromMascot
        If nonMatch > 0 Then
            Dim msgStr As String = _
              "Note: " & nonMatch & _
              " peptides did not have the number of the same modification as " & _
              " expected from the sequence " & _
              "('fixed' modification condition not fullfilled). " & _
              "Sample query number: " & _
              mMultModCounter.sampleQueryNumberForNonMatchingAAs & ". " & _
              "Those peptides have (effectively) been ignored. Stats: " & _
              mMultModCounter.totalPeptides & _
              " peptides in all. " & _
                mMultModCounter.peptidesWithModificationForQuantMode & _
              " had modification matching the quantitation mode."

            'Changed PM_REPORTS 2006-08-15
            'MsgBox(msgStr)
            mParseReport.AddItem2(10, 0, msgStr)
        End If

        'Changed PM_PARSEREPORT_IDCOUNT 2008-04-21
        '  10000 -> 100000, etc. Change in 6 different places


        'Changed PM_REFACTOR 2006-09-02
        Dim textPrefix As String = "Modification lines in the result file"
        If True Then
            mParseReport.AddItem2( _
              100000, _
              0, _
              textPrefix)

            Dim counter As Integer = 0

            'Changed PM_TYPESAFE 2007-08-08
            'Dim hashEnumerator As IDictionaryEnumerator = _
            '  mRawModStats.GetEnumerator()
            Dim hashEnumerator2 As _
              Generic.Dictionary(Of String, Integer).Enumerator = _
                mRawModStats2.GetEnumerator()

            While (hashEnumerator2.MoveNext())

                'Dim key As Integer = CInt(hashEnumerator.Key)

                mParseReport.AddItem2( _
                  100001 + counter, _
                  1, _
                  hashEnumerator2.Current.Value.ToString & ControlChars.Tab & _
                  hashEnumerator2.Current.Key.ToString)
                counter += 1
            End While
        End If

        If True Then
            mParseReport.AddItem2( _
              200000, _
              0, _
              textPrefix & ", not recognised")

            Dim counter As Integer = 0

            'Changed PM_TYPESAFE 2007-08-08
            'Dim hashEnumerator As IDictionaryEnumerator = _
            '  mNoRecognisedModStats.GetEnumerator()
            Dim hashEnumerator2 As _
              Generic.Dictionary(Of String, Integer).Enumerator = _
                mNoRecognisedModStats2.GetEnumerator()

            While (hashEnumerator2.MoveNext())
                mParseReport.AddItem2( _
                  200001 + counter, _
                  1, _
                  hashEnumerator2.Current.Value.ToString & ControlChars.Tab & _
                  hashEnumerator2.Current.Key.ToString)
                counter += 1
            End While
        End If

        If True Then
            Dim quantitationModesObject As QuantitationModes_moreGeneral = _
              mApplication.getQuantModes()

            mParseReport.AddItem2( _
              300000, _
              0, _
              textPrefix & ", recognised")

            Dim counter As Integer = 0

            'Changed PM_TYPESAFE 2007-08-08
            'Dim hashEnumerator As IDictionaryEnumerator = _
            '  mRecognisedModStats.GetEnumerator()
            Dim hashEnumerator2 As _
              Generic.Dictionary(Of Integer, Integer).Enumerator = _
                mRecognisedModStats2.GetEnumerator()

            While (hashEnumerator2.MoveNext())

                Dim modID As Integer = hashEnumerator2.Current.Key

                'Later: look up name of modification and output that as well...

                'Changed PM_MODNAME_RECOGNISED 2006-09-12
                Dim modInfo As quantModificationStructure = _
                  quantitationModesObject.getModification(modID)

                mParseReport.AddItem2( _
                  300001 + counter, _
                  1, _
                  hashEnumerator2.Current.Value.ToString & ControlChars.Tab & _
                  modInfo.modificationName & ControlChars.Tab & modID.ToString)
                counter += 1
            End While
        End If
    End Sub 'postProteinParsing2


    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Private Sub chunk_ParsingProteins( _
        ByRef anOutProcessedCount As Integer, _
        ByRef anOutEstimatedEndCount As Integer, _
        ByRef anOutPhaseTransition As Boolean _
        )

        Dim done As Boolean = False
        Dim i As Integer = 0
        Dim quantitationModesObject As QuantitationModes_moreGeneral = _
          mApplication.getQuantModes()

        While (Not mChunkedParsingInfo.chunkerParsing.timeIsUp()) And _
               Not done

            i = mChunkedParsingInfo.chunkerParsing.currentNumber()

            Dim proteinHit As ProteinHitStructure = _
              helper.blankProtein() 'Keep compiler happy.

            'Changed PM_REFACTOR 2006-03-16. No need.
            ''need to create the peptide Array list and attach it
            'Dim peptArrayList As New ArrayList(20)
            'proteinHit.pepts = thePeptArrayList

            Dim curMatchedProtein As Match = mChunkedParsingInfo.matchCol.Item(i)
            'theprotHitStru.hitNumber = CInt(theMatchCol.Item(i).Groups(1).Value)
            proteinHit.hitNumber = CInt(curMatchedProtein.Groups(1).Value)

            'Changed PM_MASCOT2_SUPPORT 2004-03-01
            If mChunkedParsingInfo.firstHitNumber = proteinHit.hitNumber Then
                Trace.Assert(False, _
                  "PIL ASSERT. Internal error, apparent multiple hit numbers, hit number=" & _
                  mChunkedParsingInfo.firstHitNumber)
            End If

            If mChunkedParsingInfo.firstHitNumber = -1 Then
                mChunkedParsingInfo.firstHitNumber = proteinHit.hitNumber
            End If

            'Mark 3

            'Changed PM_EDWIN_ALLPEPTIDES_EXPORT 2003-04-16
            'Stuff the Mascot result file name (full path) into each protein
            'for later use.
            proteinHit.resultFilePath2 = _
              mChunkedParsingInfo.mascotResultFileToParse 'aInfoFilePath

            'Changed PM_EXPORT_QUANTIFIED 2003-03-12
            proteinHit.proteinHasBeenQuantified = False

            'Protein hit is between iStart and iEnd.

            Dim iEnd As Integer = -1

            'Start of this protein hit.
            Dim iStart As Integer = _
              mChunkedParsingInfo.matchCol.Item(i).Index()

            If i < mChunkedParsingInfo.numProteinsParsed - 1 Then
                'we take everything until start of next protein
                iEnd = mChunkedParsingInfo.matchCol.Item(i + 1).Index()
            Else 'for the last one we advance to the table end
                'Changed PM_MASCOT2_SUPPORT 2004-03-01. Old way no longer
                'works because Mascot 2.0 uses TBODY/TABLE, e.g. 6 times
                'before the final TBODY/TABLE. We use <HR> instead
                'iEnd = mMascotResStr.IndexOf("</TBODY></TABLE>", iStart)
                iEnd = mMascotResStr.IndexOf("<HR>", iStart)
            End If

            'String representing the table for one protein hit, including the 
            'protein description and peptide table.
            Dim proteinTableString As String = _
              mMascotResStr.Substring(iStart, iEnd - iStart + 1)
            Dim prStrLen As Integer = proteinTableString.Length
            If prStrLen > 100000 Then
                Dim peter10 As Integer = 10
            End If

            Dim noQuantMode As Boolean = _
              quantitationModesObject.isNoQuantitationMode( _
                mParseOptions.quantModeCode)
            Dim considerModifications As Boolean = Not noQuantMode

            'Changed PM_MODIFICATIONS_FOR_NOISOTOPE 2004-08-26
            considerModifications = True

            Me.ParseOneProteinHitTable( _
               proteinTableString, proteinHit, considerModifications, i)

            If Me.doAddProtein(proteinHit) Then
                'Changed PM_CORR_RETENTIONTIME 2003-09-10

                'Changed PM_INSERTPEPTIDES_ASSERT 2005-07-29. Now only add information
                'about the peptides if we are going to insert new ones later.
                If Not mChunkedParsingInfo.corrSettings.doNotInsertNewPeptides Then
                    'Changed PM_NOISOTOPE_BROKEN 2004-11-29. Added parameter
                    'to let the function decide to accept all 
                    'peptides for 'No isotope mode'.

                    'Changed PM_MARKER_VALIDATION_AS_PEPTFILTER 2007-09-05. Uses the old
                    '  field peptDefaultValidationScoreThr2. What should it be?
                    mRetentionTimeCorrelator.updateWithPeptidesFromOneProtein( _
                      proteinHit, mChunkedParsingInfo.proteinsInTable, _
                      mChunkedParsingInfo.options.peptDefaultValidationScoreThr2, _
                      noQuantMode)

                    'Second parameter seems to be a zero-based index. Why
                    'do we pass something that looks like a one-based count?
                    '
                    'Answer: it happens to be like a zero based index at this time.
                    '        It is updated after this call, below.
                End If

                mParsedProts2.Add(proteinHit) 'This works because it is
                '  a structure. ??
                mChunkedParsingInfo.proteinsInTable += 1
            End If
        End While

        'Changed PM_INSERTPEPTIDES_ASSERT 2005-07-29
        'This construct is for ASSERT only.
        If mChunkedParsingInfo.corrSettings.doNotInsertNewPeptides Then
            'If we are not going to insert new peptides then we will not bother
            'with the correlation (even though it could be interesting to know about
            'the retention time correlation)
            Trace.Assert(mRetentionTimeCorrelator.insertedPeptides() = 0, _
              "PIL ASSERT. BAD: Inserted peptides even though the option is turned off.")
        End If

        If mChunkedParsingInfo.chunkerParsing.jobFinished() Then

            'Changed PM_MEMORY_ALLOCATION 2004-07-31
            mFilteredPepLinesSB = Nothing

            'Changed PM_MEMORY_ALLOCATION 2004-08-06
            Dim memDiffMB As Double
            Dim tickTimeSecs As Double
            quantApplication.GarbageCollect(mLogger, memDiffMB, tickTimeSecs)

            quantApplication.stopNow("Done parsing proteins", True)

            If True Then 'Some kind of error detection here.
                mChunkedParsingInfo.majorState = _
                  parsingPhaseEnum.enumOtherParsingXYZ

                'Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-24
                'Dim parsePeptideFilter As peptideFilterSpecificationStructure = _
                '  mParseOptions.peptideFilterSpecification
                Dim parsePeptideFilter As peptideFilterStructure = _
                  mParseOptions.peptideFilters(peptideFilterEnum.enumParsing2)

                'No! Recalibration has not been applied yet!
                ''Display mass errors before insertion of new peptides.
                ''The correct solution would be to have a peptide filter
                ''with 
                '    Dim recalibVisualForm As frmRecalibrationVisualisation = _
                '      New frmRecalibrationVisualisation( _
                '        Nothing, mParsedProts2, parsePeptideFilter)
                '    recalibVisualForm.Show()

                'Inserting new peptides (retention time correlation only).
                'And sorting of peptides (still physical sort?).
                'Rename function??
                quantApplication.postProteinParsing( _
                  mRetentionTimeCorrelator, _
                  mRawFiles, _
                  mChunkedParsingInfo.corrSettings.doNotInsertNewPeptides, _
                  mParsedProts2, _
                  mMultipleRawFilesHandling, _
                  mChunkedParsingInfo.corrSettings.insertPeptidesInLCTimeRange, _
                  mChunkedParsingInfo.corrSettings.startLCtimeForInsertion_Secs, _
                  mChunkedParsingInfo.corrSettings.endLCtimeForInsertion_Secs, _
                  parsePeptideFilter, _
                  mApplication _
                  )

                'Changed PM_REFACTOR 2006-10-25
                Me.postProteinParsing2() 'Creating parsing report. Rename function??

                'Changed PM_MEMORY_ALLOCATION 2004-08-06
                Dim memDiffMB2 As Double
                Dim tickTimeSecs2 As Double
                quantApplication.GarbageCollect( _
                  mLogger, memDiffMB2, tickTimeSecs2)
            Else
                mChunkedParsingInfo.majorState = _
                  parsingPhaseEnum.enumParsingError
            End If

            'Changed PM_MISSING_STATE_CHANGE_INDICATION 2004-07-30
            anOutPhaseTransition = True
        End If
        anOutProcessedCount = i + 1 '1 because i is zero-based
        anOutEstimatedEndCount = mChunkedParsingInfo.numProteinsParsed
    End Sub 'chunk_ParsingProteins


    'Changed PM_PARSE_CHUNKED 2004-04-06
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Public Function doChunkParsing( _
      ByRef anOutProcessedCount As Integer, _
      ByRef anOutEstimatedEndCount As Integer, _
      ByRef anOutStats As parsingStatsStructure, _
      ByRef anOutPhaseTransition As Boolean, _
      ByRef aReadBuffer() As Char, _
      ByVal aBufferSize As Integer, _
      ByRef aEOLcharacters() As Char _
      ) _
      As Boolean

        Dim toReturn As Boolean = True
        anOutPhaseTransition = False
        anOutStats.bytesReadInThisChunk = 0

        Dim startState As parsingPhaseEnum = mChunkedParsingInfo.majorState

        Select Case mChunkedParsingInfo.majorState
            Case parsingPhaseEnum.enumReadingFile
                Me.chunk_FileRead( _
                  aReadBuffer, aBufferSize, aEOLcharacters, _
                  anOutProcessedCount, anOutEstimatedEndCount, _
                  anOutStats, anOutPhaseTransition)

            Case parsingPhaseEnum.enumParsingToolTips
                Me.chunk_ParsingToolTips( _
                  anOutProcessedCount, anOutEstimatedEndCount, _
                  anOutPhaseTransition)

            Case parsingPhaseEnum.enumParsingProteins
                Me.chunk_ParsingProteins( _
                  anOutProcessedCount, anOutEstimatedEndCount, _
                  anOutPhaseTransition)

            Case parsingPhaseEnum.enumOtherParsingXYZ
                'End state....
                toReturn = False

            Case parsingPhaseEnum.enumParsingError
                'End state, but in error....
                toReturn = False

            Case Else
                Trace.Assert(False, _
                  "PIL ASSERT. Select Case never fall-through. " & _
                  "In doChunkParsing(). State is: " & startState & ".")
        End Select 'mChunkedParsingInfo.majorState

        anOutStats.curState = mChunkedParsingInfo.majorState

        'Changed PM_MEMORY_PROBLEM 2004-04-13
        If Not toReturn Then
            mChunkedParsingInfo.chunkerParsing = Nothing
            mChunkedParsingInfo.inputFileStream = Nothing
            mChunkedParsingInfo.inputStreamReader = Nothing
            mChunkedParsingInfo.matchCol = Nothing

            'mChunkedParsingInfo.toolTipItems = Nothing
        End If

        'For breakpoints.
        If anOutPhaseTransition Then
            Dim peter4 As Integer = 4
        End If
        If anOutStats.curState = parsingPhaseEnum.enumParsingError Then
            Dim peter3 As Integer = 3
        End If

        Return toReturn
    End Function 'doChunkParsing


    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Private Function doAddProtein( _
      ByVal aProt As ProteinHitStructure) As Boolean

        Dim toReturn As Boolean = True

        'First condition: Add no proteins from IPI? This is the case
        'for the Malaria project.
        If mParseOptions.dontShowIPI And _
           aProt.accNum.ToUpper.StartsWith("IPI") Then

            toReturn = False
        End If

        'Changed PM_ALLOW_PROTEINS_WITH_ONLY_D_PEPTIDES 2008-02-29. Disabled
        '  this. Effectively the hidden option "" is now checked off.
        ' 'Changed PM_HIGHESTUNIQUELY_BADVALUES 2008-02-29. Note: we
        ' '  no longer have numPeptsInA > 0 as computing these have been postponed
        ' '  to the end of parse, in setCalibratedValues(), file SDUPrecalibrator.vb.
        ' Trace.Assert(mParseOptions.dontShowProtWithNoPeptInABC = False, _
        '   "PIL ASSERT. dontShowProtWithNoPeptInABC is true...")
        ' 
        ' 'Second condition: Add protein without high scoring peptides?
        ' If mParseOptions.dontShowProtWithNoPeptInABC And _
        '   (aProt.numPeptsInA = 0 And aProt.numPeptsInB = 0 And _
        '    aProt.numPeptsInC = 0) Then
        ' 
        '     toReturn = False
        ' End If

        'Changed PM_HIGHESTUNIQUELY_BADVALUES 2008-02-29
        If aProt.peptides Is Nothing Then
            toReturn = False 'No peptides ever added to current protein. Nothing
            '  comes from the lazy instantitation...
        Else
            'Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-27
            Dim pepIter As peptideListIterator = _
              New peptideListIterator(aProt.peptides)
            Dim token As Integer = pepIter.getIterToken()

            'Changed PM_REFACTOR 2006-03-16
            ''Changed PM_EXCLUDE_EMPTY_PROTEINS 2005-07-29
            'If aProt.pepts.Count = 0 Then
            If aProt.peptides.peptideCount(token) = 0 Then
                toReturn = False
            End If
        End If

        Return toReturn
    End Function 'doAddProtein


    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Private Sub parseProteinInfo(ByRef aPeptideTableWithHeader As String, _
      ByRef anOutprotHitStru As simpleProteinInfoStructure)

        Dim len As Integer = aPeptideTableWithHeader.Length

        'Extract information about the protein.

        'Changed PM_MASCOT2_SUPPORT 2004-03-01
        'Accession number is in the anchor tag betweeen "> and end anchor tag
        'a quote in quotes allows matching a single quote
        ';protscore=824.126233769285">PFM1335c</A>             <B>Mass:</B>
        'sometimes there is no accession number:
        'Update for Mascot 2:
        '  No longer " before the > , as in 
        '    "  target=_blank>Q8CCQ4</A>     "
        '
        'result = Regex.Match(anInProtTableStr, """>(.+)</A>")
        'Dim result As Match = _
        '  Regex.Match(aPeptideTableWithHeader, "http[^>]+>(.+)</A>[^c]+core")
        Dim result As Match = _
          Regex.Match(aPeptideTableWithHeader, "http[^>]+>([^<]+)</A>")

        If result.Success Then
            anOutprotHitStru.accessionNumber = result.Groups(1).Value
            Trace.Assert(anOutprotHitStru.accessionNumber.Length < 40, _
              "PIL ASSERT. Accession number is longer than 40 characters. " & _
              "There is probably something wrong with the format of " & _
              "the Mascot result (.htm/.html) file ")
        Else
            anOutprotHitStru.accessionNumber = ""
        End If

        'mass: <B>Mass:</B> 29856
        '\s+ because there is at least one whitespace.
        result = Regex.Match(aPeptideTableWithHeader, "<B>Mass:</B>\D*(\d+)")
        If result.Success Then
            'Changed PM_PROTEINMASS_DECIMAL 2006-03-22
            'anOutprotHitStru.mass = CInt(result.Groups(1).Value)
            anOutprotHitStru.mass = CDbl(result.Groups(1).Value)
        Else
            anOutprotHitStru.mass = -1
        End If

        'Changed PM_NEWMASCOT2_FORMAT 2004-06-17
        Dim noFontColoursStr As String = _
          aPeptideTableWithHeader.Replace("#ff0000", "")

        'Changed PM_MASCOT2_SUPPORT 2004-03-01
        'We are not interested in the total score, only for cross check purposes.
        '<B>Total score:</B> 24
        'Mascot 2 update: 
        '  <B>Score:</B> 38 
        'Mascot 2.xx update:
        '  <B>Score:</B> <FONT       color=#ff0000><B>926  </B></FONT>
        '
        ''result = Regex.Match(anInProtTableStr, "<B>Total score:</B>\s*(\d+)")
        'result = Regex.Match(aPeptideTableWithHeader, "core:\D*(\d+)")
        result = Regex.Match(noFontColoursStr, "core:\D*(\d+)")

        anOutprotHitStru.totalScore = CInt(result.Groups(1).Value)

        'Changed PM_MASCOT2_SUPPORT 2004-03-01
        '<B>Peptides matched:</B> 2
        'Mascot 2.0 update:
        '  <B>Peptides matched:</B> 1</TT>
        '
        'Mascot 2.xx update:
        '  <B>Queries       matched:</B> 48</TT>

        'Changed PM_NEWMASCOT2_FORMAT 2004-06-17
        ''result = Regex.Match(anInProtTableStr, "<B>Peptides matched:</B>\s*(\d+)")
        'result = Regex.Match(aPeptideTableWithHeader, _
        '  "<B>Peptides\s+matched:</B>\D*(\d+)")
        result = Regex.Match(aPeptideTableWithHeader, _
          "es\s+matched:</B>\D*(\d+)")

        anOutprotHitStru.totalPeptides = CInt(result.Groups(1).Value)

        Dim lenta2 As Integer = aPeptideTableWithHeader.Length

        'Changed PM_MEMORY_ALLOCATION 2004-07-29
        'Dim parts1 As String()
        Dim match1a As Match

        Try
            'Now extract the protein description.
            '
            'Mascot 1.x: this is simply the next line without any formating
            '  look for next carrige return line feed and move just past it (2 chars)
            'Mascot 2.0: very different.
            '
            'To accomodate both versions we split on some strings before
            'and after the description and then remove HTML tags.
            If True Then
                Try
                    Dim hlen As Integer = aPeptideTableWithHeader.Length
                    'Changed PM_NEWMASCOT2_FORMAT 2004-06-17
                    'parts1 = _
                    '  Regex.Split(aPeptideTableWithHeader, _
                    '    "<B>Peptides\s+matched:</B>\D*\d+")

                    'Changed PM_MEMORY_ALLOCATION 2004-07-29
                    'parts1 = _
                    '  Regex.Split(aPeptideTableWithHeader, _
                    '    "es\s+matched:</B>\D*\d+")

                    match1a = _
                      Regex.Match(aPeptideTableWithHeader, "es\s+matched:</B>\D*\d+(.*)")

                    'Dim iStart As Integer = mChunkedParsingInfo.matchCol.Item(i).Index() 'Start of this protein hit.

                Catch exceptionObject As Exception
                    Dim errMsg1 As String = "Error: " & exceptionObject.ToString & ControlChars.NewLine
                    Dim errMsg2 As String = _
                      "Message: " & exceptionObject.Message & ControlChars.NewLine
                    Dim errMsg3 As String = ""
                    If Not exceptionObject.InnerException Is Nothing Then
                        errMsg3 = _
                            "Extra info: " & exceptionObject.InnerException.Message & ControlChars.NewLine
                    End If
                    Dim errMsg As String = errMsg1 & errMsg2 & errMsg3
                    MsgBox(errMsg)
                    Exit Sub
                End Try

                Try
                    Dim after1 As String = match1a.Groups(1).Value
                    Dim after1Len As Integer = after1.Length()

                    'Changed PM_MARKER_PARSE_OPTIMISATION_OPPORTUNITY 2007-12-14
                    'Note: we are only interested in the protein description
                    '      here. We could use string search/IndexOf to cut
                    '      out the sections before the second "noWrap".

                    Dim Matches3 As MatchCollection = _
                      Regex.Matches(after1, "(.+?)noWrap>")

                    'Changed PM_MARKER_REDUCTORSCRIPT_TROUBLE 2007-12-14
                    Dim len3 As Integer = Matches3.Count 'For some output of
                    '  script MascotResultFileReductor.pl it stays in this
                    '  for a very long time... Why????
                    '
                    '  From documentation:
                    '    "Note that as soon as the Count property is 
                    '    accessed, the regular expression engine must 
                    '    be run to find all matches."

                    'Note: compared to split we don't have the last part.

                    Dim after3 As String
                    If len3 <= 1 Then
                        If len3 = 1 Then
                            after3 = after1
                        Else
                            Dim peter3 As Integer = 3
                            after3 = after1 'So as not to fail...
                        End If
                    Else
                        'Changed PM_MASCOT2_SUPPORT_MASCOT1XDESCR_TROUBLE 2004-03-16
                        after3 = _
                          Matches3.Item(0).Groups(0).Value & " " & _
                          Matches3.Item(1).Groups(0).Value
                    End If

                    after3 = after3.Replace("<TT>", "")

                    'Would this be more memory efficient? (removing any HTML tags):
                    '  Dim after4 As String = Regex.Replace(after3, "<.*?>", "")

                    'Remove tags before the description. This is only for Mascot 2.0
                    Dim after4 As String
                    after4 = after3.Replace("</TT>", "")
                    after4 = after4.Replace("</TD>", "")
                    after4 = after4.Replace("</TR>", "")
                    after4 = after4.Replace("<TR>", "")
                    after4 = after4.Replace("<TD>", "")

                    after4 = after4.Replace(" ", "")

                    'Changed PM_MASCOT2_SUPPORT_MASCOT1XDESCR_TROUBLE 2004-03-16
                    after4 = after4.Replace("<TD", "")

                    'Changed PM_MEMORY_PROBLEM_NOSPLITS 2004-04-13
                    after4 = after4.Replace("noWrap>", "")

                    'Changed PM_MASCOT22_EMPAI_TROUBLE 2007-04-16.
                    'Note: will include the emPAI information in the protein
                    '      description. Is that what we want?
                    after4 = after4.Replace("<B>", "")
                    after4 = after4.Replace("</B>", "")


                    Dim index1 As Integer
                    Dim len1 As Integer
                    Dim index2 As Integer
                    Dim len2 As Integer
                    MascotResultParser.split2( _
                      after4, "<", index1, len1, index2, len2, True)
                    Dim after5 As String = after4.Substring(index1, len1)

                    Dim after6 As String = after5.Trim()

                    anOutprotHitStru.description = after6

                Catch exceptionObject As Exception
                    Dim errMsg1 As String = "Error: " & exceptionObject.ToString & ControlChars.NewLine
                    Dim errMsg2 As String = _
                      "Message: " & exceptionObject.Message & ControlChars.NewLine
                    Dim errMsg3 As String = ""
                    If Not exceptionObject.InnerException Is Nothing Then
                        errMsg3 = _
                            "Extra info: " & exceptionObject.InnerException.Message & ControlChars.NewLine
                    End If
                    Dim errMsg As String = errMsg1 & errMsg2 & errMsg3
                    MsgBox(errMsg)
                    Exit Sub
                End Try
            End If

        Catch exceptionObject As Exception
            If False Then 'For testing
                Dim someStr As String = "lor=#ff0000><B>462  </B></FONT>  <B>Peptides         matched:</B> 29</TT></TD></TR>    <TR>      <TD> </TD>      <TD         noWrap><TT>SWISS-PROT:Q9JK11"
                Dim parts8888 As String() = _
                                      Regex.Split(someStr, _
                                        "<B>Peptides\s+matched:</B>\D*\d+")
                Dim lenta As Integer = aPeptideTableWithHeader.Length
                Dim parts9999 As String() = _
                                      Regex.Split(aPeptideTableWithHeader, _
                                        "<B>Peptides\s+matched:</B>\D*\d+")
            End If

            Dim errMsg1 As String = "Error: " & exceptionObject.ToString & ControlChars.NewLine
            Dim errMsg2 As String = _
              "Message: " & exceptionObject.Message & ControlChars.NewLine
            Dim errMsg3 As String = ""
            If Not exceptionObject.InnerException Is Nothing Then
                errMsg3 = _
                    "Extra info: " & exceptionObject.InnerException.Message & ControlChars.NewLine
            End If
            Dim errMsg As String = errMsg1 & errMsg2 & errMsg3
            MsgBox(errMsg)
            Exit Sub
        End Try

        If anOutprotHitStru.accessionNumber.Length = 0 Then
            Dim msg As String = _
              "The protein accession number could not be found. " & ControlChars.NewLine & _
              "The Mascot result file (.htm/.html) does not have " & _
                "the correct format. " & ControlChars.NewLine & _
              "Possible reason: if you are using Mascot Result Launcher " & _
                "to get the result file be sure that the " & _
                "file ""/usr/local/mascot/cgi/master_results.pl"" on " & _
                "the Mascot server has been properly modified, " & _
                "in particular absolute (not relative) URLs in " & _
                "$pepViewLink, $protViewLink and $scoreGifLink. " & _
                "Contact your local Mascot server administrator " & _
                "with this information. " & ControlChars.NewLine & _
              "Extra info: protein description: " & anOutprotHitStru.description
            MsgBox(msg)
        End If
    End Sub 'parseProteinInfo


    'Changed PM_SEQUENCE_DEPENDENT_QUANTMASSDIFF_BUGS 2004-07-15
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Public Shared Sub resetOtherFields( _
      ByRef aPeptHitStru As PeptideHitStructure)

        'Delete at any time.
        'Changed PM_REFACTOR 2006-10-01. Not used any more..
        ''For error detection, these fields should be set later to proper values.
        'aPeptHitStru.quantNeutralMassDiff1 = -1.02E+20
        'aPeptHitStru.quantNeutralMassDiff2 = -1.02E+20

        'Changed PM_STRING_CLEANUP 2004-12-14
        aPeptHitStru.AASequencePlusMods = Nothing

        'Do not reset yet, will contain a TAB: aPeptHitStru.badPeakReason

        'Assert to these to ensure they do not already contain something??

        aPeptHitStru.comment = Nothing
        aPeptHitStru.importedAcc = Nothing
        aPeptHitStru.MS3precursorStr = Nothing

        'Changed PM_RAWFILE_RESET 2005-01-19. Do not reset as it is
        'always set, at least before this function is called.
        'aPeptHitStru.rawFileFullPath = Nothing
        'Later get the path on demand? As in:
        '  aPeptHitStru.rawFileFullPath = _
        '    rawDataFileHandling.getFullRawFilePath(mRawFiles, .qRawFileID)

        aPeptHitStru.secSequence = Nothing
        aPeptHitStru.seq1 = Nothing
        aPeptHitStru.seq2 = Nothing
    End Sub 'resetOtherFields


    'Changed PM_REFACTOR_INSERT_NATIVEPEPTIDE 2003-10-15
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Public Shared Sub resetModFields( _
      ByRef aModHits As Generic.List(Of modificationCountStruct))

        'Old:
        '  ByRef aModHits As ArrayList

        aModHits = Nothing 'Note: we use lazy instantiation....
    End Sub 'resetModFields


    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Private Sub ParseOneProteinHitTable( _
      ByRef aProtTableStr3 As String, _
      ByRef aProtHitStru As ProteinHitStructure, _
      ByVal aUseMod As Boolean, _
      ByVal aProteinIndex As Integer)

        'Changed PM_EVENMORE_GENERALISED_QUANTMODES 2005-04-08
        'Old param:
        '  ByVal aQuantValues As massSpectrometryBase.quantValuesStructure


        'Changed PM_IGNORED_PEPTIDES_EXPOSED 2007-09-05
        'Perhaps require filters as parameters (to not spread  
        'enumParsing2 and enumValidationParse in too many places)?
        '
        'Why do we need to do this for every protein??
        Dim parsePeptideFilter As peptideFilterStructure = _
          mParseOptions.peptideFilters(peptideFilterEnum.enumParsing2)

        ''Changed PM_VALIDATION_AS_PEPTFILTER 2007-09-05
        'Dim validationFilter As peptideFilterStructure = _
        '  mParseOptions.peptideFilters(peptideFilterEnum.enumValidationParse)

        Dim matchStr As String = "<B>Proteins matching the same"
        Dim matchIndex As Integer = aProtTableStr3.IndexOf(matchStr)
        Dim foundMatchingSameSection As Boolean = False

        If matchIndex >= 0 Then
            Dim matchIndex2 As Integer = _
              aProtTableStr3.IndexOf(matchStr, matchIndex + 1) 'For the
            '  assert below.

            Trace.Assert(matchIndex2 < 0, _
              "PIL ASSERT. The number of sections " & _
              "with 'Proteins matching the same set of peptides' is " & _
              "greater than 1. Input string: " & _
                ControlChars.NewLine & ControlChars.NewLine & aProtTableStr3)
        Else
            'Not found, use the whole string
            matchIndex = aProtTableStr3.Length
            foundMatchingSameSection = True
        End If

        Dim samePeptidesMatchingLen As Integer = _
          aProtTableStr3.Length - matchIndex

        Dim proteinsMatchingSamePeptides As String = ""

        'Is there any difference in terms of memory allocations
        'between assignment and Substring()?
        Dim peptideTableWithHeader As String
        If samePeptidesMatchingLen > 0 Then
            peptideTableWithHeader = aProtTableStr3.Substring(0, matchIndex)
            proteinsMatchingSamePeptides = _
              aProtTableStr3.Substring(matchIndex, samePeptidesMatchingLen)
        Else
            peptideTableWithHeader = aProtTableStr3
        End If

        Dim topProtein As simpleProteinInfoStructure
        topProtein.accessionNumber = Nothing 'Keep compiler happy.
        topProtein.description = Nothing 'Keep compiler happy.

        parseProteinInfo(peptideTableWithHeader, topProtein)

        aProtHitStru.accNum = topProtein.accessionNumber
        aProtHitStru.monoIsotopicMass = topProtein.mass
        aProtHitStru.MascotTotalScore = topProtein.totalScore
        aProtHitStru.MascotTotalPepts = topProtein.totalPeptides
        aProtHitStru.description2 = topProtein.description

        'Now we extract information about the peptides.

        'Parse the peptide table for this protein one peptide result line at a
        'time by capturing everything between the row delimitors <TR> and </TR>
        Dim resultCol2 As MatchCollection = _
          Regex.Matches(peptideTableWithHeader, "<TR>(.*?)</TR>")

        'Changed PM_MEMORY_ALLOCATION 2004-07-28. For statistics.
        Dim items As Integer = 0
        Dim filteredItems As Integer = 0

        'Changed PM_MASCOT2_SUPPORT 2004-03-01
        'Filter out any lines not containing 'title'  - or is it 'statusString'?

        'Changed PM_MEMORY_ALLOCATION 2004-07-28
        'Dim filteredPepLines As String = ""
        Dim maxStrLength As Integer = aProtTableStr3.Length 'Typical value
        '  is 40 KB.

        If mFilteredPepLinesSB Is Nothing Then 'Lazy instantiation...
            mFilteredPepLinesSB = New StringBuilder(2 * maxStrLength)
        Else
            'Reuse existing object.
            mFilteredPepLinesSB.Length = 0
        End If

        Dim pepLineMatch As Match
        For Each pepLineMatch In resultCol2
            'Changed PM_MEMORY_ALLOCATION 2004-07-28. Direct use of pepLine.Value
            Dim result3 As Match = Regex.Match(pepLineMatch.Value, "statusString")
            If result3.Length > 0 Then
                'Changed PM_MEMORY_ALLOCATION 2004-07-28
                'filteredPepLines &= "<TR>" & pepLine.Value & "</TR>"
                mFilteredPepLinesSB.Append("<TR>")

                'For debugging. Does it create more memory garbage?
                'mFilteredPepLinesSB.Append(pepLine.Value)
                Dim pepLineStr As String = pepLineMatch.Value
                mFilteredPepLinesSB.Append(pepLineStr)

                mFilteredPepLinesSB.Append("</TR>")

                filteredItems += 1
            Else
                Dim peter2 As Integer = 2 'When does this happen?
            End If
            items += 1
        Next

        'Changed PM_MEMORY_ALLOCATION 2004-07-28
        Dim filteredPepLines As String = mFilteredPepLinesSB.ToString

        'Changed PM_MEMORY_ALLOCATION 2004-07-31
        'filteredPepLinesSB = Nothing

        Dim resultCol As MatchCollection = _
          Regex.Matches(filteredPepLines, "<TR>(.*?)</TR>")

        Dim i As Integer
        Dim numPeptMatches As Integer = resultCol.Count

        'Reset everything that has a running sum ("+="), modifications, etc.
        With aProtHitStru

            'Not really needed anymore. It is done in setCalibratedValues().
            .numPeptsInA = 0
            .numPeptsInB = 0
            .numPeptsInC = 0
            .scoreInABC = 0
            .peptsInABC = 0


            'Changed PM_REFACTOR 2006-10-10
            ''Changed PM_PROTEINRATIO_FOR_EACH_RAWFILE 2006-02-27
            '.quantResults = Nothing
            .quantResults3 = Nothing

            'Changed PM_HIGHESTUNIQUELY_BADVALUES 2008-02-29. Now set 
            '  through a candidate list.
            ''Changed PM_REFACTOR_HOTSPOT 2006-03-16
            '.peptides = New PILpeptides(numPeptMatches)



            .effectivePeptideCount = 0
        End With

        'Changed PM_HIGHESTUNIQUELY_BADVALUES 2008-02-29
        Dim peptideList As massSpectrometryBase.PILpeptides = _
          Nothing 'Lazy instantiation.


        'Changed PM_GENERALISED_QUANT_MODE 2003-12-08
        Dim quantitationModesObject As QuantitationModes_moreGeneral = _
          mApplication.getQuantModes()
        Dim curQuantMode As _
          generalisedQuantModeStructure = _
            quantitationModesObject.getQuantitationMode( _
              mParseOptions.quantModeCode)

        Dim numPepts As Integer 'For test.
        Dim totalScore As Integer 'For test.

        Dim addedPeptides As Integer = 0

        'Changed PM_PROTEINVAL_REQUIRES_PEPTIDEVALS 2007-08-31
        'Dim verifiedPeptides As Integer = 0

        'Changed PM_MASCOT2_SUPPORT 2004-03-01
        'For i = 1 To numPeptMatches - 1 '1 because the first match
        '  is table heading.
        For i = 0 To numPeptMatches - 1 'Now 0 because of our prefiltering.

            Dim pept As PeptideHitStructure = _
              helper.blankPeptide() 'Keep compiler happy.

            'Extract a single peptide row in the sub.
            Me.ParsePeptMatch( _
              resultCol.Item(i).Groups(0).Value, _
              pept, aUseMod)

            'For consistency check.
            numPepts += 1

            'Assume peptide is valid and go through all cases where
            'it would not be valid:
            Dim countThisPept As Boolean = True

            If pept.scoreInParens And Not mParseOptions.inclPeptsInParens Then
                countThisPept = False
                totalScore += pept.MascotScore 'Just for checking with
                '  total mascot score.
            End If

            'Changed PM_PARSE_PEPTIDE_CHECKED_STATE 2007-05-01. Why was
            '  it set to true??
            ''Changed PM_NEWMASCOT2_FORMAT 2004-06-17
            'pept.checkboxChecked = True 'For now!!!!!!!!!!

            'If it is a red peptide and we require (Mascot result page)
            'CheckBox() checked then the checkbox needs to be
            'checked, otherwise it's out.
            If (pept.MascotColour = mascotColourEnum.enumLightRed Or _
                pept.MascotColour = mascotColourEnum.enumBoldRed) And _
              mParseOptions.inclRedPeptsIfCheckedOnly Then
                If Not pept.checkboxChecked Then
                    countThisPept = False
                End If
            End If

            If pept.MascotColour = mascotColourEnum.enumBoldRed And _
              Not mParseOptions.inclBoldRedPepts Then
                countThisPept = False
            End If

            If pept.MascotColour = mascotColourEnum.enumLightRed And _
              Not mParseOptions.inclLightRedPepts Then
                countThisPept = False
            End If

            'Changed PM_PARSED_BOLDBLACK_BUG 2007-05-01. Logic for the two 
            '  options must be combined as they both work on the same
            '  set of boldness/colour:
            '    Bold black peptides.
            '
            ' 'If peptide is in black but option excludes this then it's out.
            ' If pept.MascotColour = mascotColourEnum.enumBoldBlack And _
            '   Not mParseOptions.inclBoldBlackPepts Then
            '     countThisPept = False
            ' End If
            ' 
            ' 'If peptide is black and option says it needs to be checked but
            ' 'it isn't then its out.
            ' '
            ' 'Changed PM_PARSED_BOLDBLACK_BUG 2007-05-01. This bug was present
            ' '  since the beginning of this program!!
            ' '  Should we keep the condition on parenthesised?
            ' '
            ' ' If pept.MascotColour = mascotColourEnum.enumBoldBlack And _
            ' '   Not mParseOptions.inclBoldBlackPeptsIfChecked Then
            ' ' 
            ' '     If Not pept.scoreInParens Then
            ' '         countThisPept = False
            ' '     End If
            ' ' End If
            ' If (pept.MascotColour = mascotColourEnum.enumBoldBlack And _
            '     pept.checkboxChecked = True) _
            '   And _
            '   Not mParseOptions.inclBoldBlackPeptsIfChecked Then
            ' 
            '     countThisPept = False
            ' End If
            If pept.MascotColour = mascotColourEnum.enumBoldBlack Then

                Dim includeA_BoldBlack As Boolean = False

                If mParseOptions.inclBoldBlackPeptsIfChecked Then
                    If pept.checkboxChecked Then
                        includeA_BoldBlack = True
                    End If
                End If

                If mParseOptions.inclBoldBlackPepts Then
                    includeA_BoldBlack = True
                End If

                If Not includeA_BoldBlack Then
                    countThisPept = False
                End If
            End If

            'We don't count the peptide if it is in light black no matter what.
            If pept.MascotColour = _
              mascotColourEnum.enumLightBlack Then
                countThisPept = False
            End If

            'Changed PM_MODIFICATION_FILTER 2004-12-07
            If countThisPept Then 'This check is an optimisation...
                If mModHash2.Count > 0 Then 'Any filter specified?

                    'Changed PM_REFACTOR 2007-08-29. Delete outcommented at any time.
                    ' If True Then
                    '     'Changed PM_REFACTOR 2006-10-22
                    '     'Dim mods As ArrayList = pept.modHits
                    '     Dim mods2 As Generic.List(Of modificationCountStructure) = _
                    '       pept.modHits2
                    '
                    '     Dim anyMods As Boolean = _
                    '       Not mods2 Is Nothing AndAlso mods2.Count > 0
                    '     If anyMods Then
                    '         Dim lastIndex As Integer = mods2.Count - 1
                    '         Dim j As Integer
                    '         Dim matchedID As Boolean = False
                    '         For j = 0 To lastIndex
                    '             Dim curMod As modificationCountStructure = mods2(j)
                    '             If mModHash2.ContainsKey(curMod.quantModificationID) Then
                    '                 matchedID = True
                    '                 Exit For
                    '             End If
                    '         Next
                    '         If Not matchedID Then
                    '             countThisPept = False
                    '         Else
                    '             Dim peter8 As Integer = 8
                    '         End If
                    '     Else
                    '         'No modifications for peptide. As we have a filter then
                    '         'the peptide must be excluded....
                    '         Dim peter9 As Integer = 9
                    '         countThisPept = False
                    '     End If 'Any mods (in peptide).
                    ' End If
                    Dim mods As Boolean = _
                      peptideFilterStructure.anyModsInFilter( _
                        pept.modHits2, mModHash2)

                    countThisPept = mods 'OK as countThisPept is True at
                    '  this point.
                Else
                    'No filter. We never reject peptides in that case..
                    Dim peter11 As Integer = 11
                End If
            End If 'Modification filter.

            ''Surviving peptides' are put into A,B,C bins according to user
            'specified thresholds.


            'Changed PM_QSTAR_TROUBLE 2008-01-11.
            If False Then 'True: test only!!!!!!!!!!!!!!!!!!!!!!!!!!!

                ' phd934v1.wiff
                ' phd934v2.wiff
                ' phd934v300.wiff
                ' phd934v550.wiff

                If countThisPept Then
                    If False AndAlso pept.rawFileFullPath.IndexOf("phd934v1.wiff") > 0 Then
                        'Exclude peptides from this raw file...
                        countThisPept = False
                    Else
                        Dim peter2 As Integer = 2
                    End If

                    If False AndAlso pept.rawFileFullPath.IndexOf("phd934v550.wiff") > 0 Then
                        'Exclude peptides from this raw file...
                        countThisPept = False
                    Else
                        Dim peter2 As Integer = 2
                    End If

                    If False AndAlso pept.rawFileFullPath.IndexOf("phd934v2.wiff") > 0 Then
                        'Exclude peptides from this raw file...
                        countThisPept = False
                    Else
                        Dim peter2 As Integer = 2
                    End If

                    If False AndAlso pept.rawFileFullPath.IndexOf("phd934v300.wiff") > 0 Then
                        'Exclude peptides from this raw file...
                        countThisPept = False
                    Else
                        Dim peter2 As Integer = 2
                    End If

                End If 'Guard.
            End If 'Block. Test only.


            'Why is it set at this point??. What is ".counted" used for?
            If countThisPept Then
                pept.counted = True
            Else
                pept.counted = False
            End If

            'MM changed 26Oct2002 fill in the .verified column for peptides 
            'Const MIN_VERIF_MASCOT_SCORE As Integer = 25 'todo: move
            'into constant module

            'Changed PM_CODEMARKER 2006-11-28

            'Changed PM_EXCLUDE_NONPRESELECTED 2004-10-25. Condition added, now
            'we will not let non-preselected peptides through.
            If countThisPept Then

                'Changed PM_MEMORYEFFICIENCY_PARSE 2006-11-28. Moved here.
                'There is no need to prepare a peptide for quantitation 
                'if we are not using it!
                '
                'Note: the peptide can be invalidated by this
                '      call - sequence changed to "ZZZZZZ". E.g. if
                '      the SILAC condition is not fulfilled; fewer
                '      modified SILAC modifications than in the peptide
                '      sequence.
                '
                'Changed PM_MEMORYEFFICIENCY_PARSE 2007-02-19.
                Dim peptideInvalidated As Boolean
                pept = _
                  massSpectrometryBase.FindLCpeaks.preparePeptideForQuantitation( _
                    pept, _
                    curQuantMode, _
                    mMultModCounter, _
                    peptideInvalidated)
                countThisPept = Not peptideInvalidated

                If countThisPept Then 'SILAC rule fulfilled?
                    'Changed PM_SHORT_EXPORT 2005-12-01
                    Trace.Assert(pept.leftFlankAA <> 0, _
                      "PIL ASSERT. leftFlankAA is 0 for peptide " & _
                      pept.AASequence & _
                      ". Excel does not like that.")
                    Trace.Assert(pept.rightFlankAA <> 0, _
                      "PIL ASSERT. rightFlankAA is 0 for peptide " & _
                      pept.AASequence & _
                      ". Excel does not like that.")

                    'Changed PM_HIGHESTUNIQUELY_BADVALUES 2008-02-29
                    'Protein counts were here...
                    '
                    'Moved to setCalibratedValues(), file SDUPrecalibrator.vb.


                    'Changed PM_VALIDATION_AFTER_RECALIBRATION 2007-09-24
                    ' If True Then 'Peptide validation.
                    '     pept.verified = False
                    ' 
                    '     'Changed PM_VALIDATION_AS_PEPTFILTER 2007-09-05
                    '     'Dim OKtoValidate As Boolean = _
                    '     '  score >= mParseOptions.peptDefaultValidationScoreThr
                    '     Dim updateModHash As Boolean
                    '     Dim OKtoValidate As Boolean = _
                    '       Not PILpeptides.simpleFilteredOut2( _
                    '         pept, validationFilter, updateModHash)
                    ' 
                    '     'Problem with uniquely highest scoring?
                    '     If OKtoValidate Then
                    '         pept.verified = True
                    ' 
                    '         'Changed PM_PROTEINVAL_REQUIRES_PEPTIDEVALS 2007-08-31
                    '         verifiedPeptides += 1
                    '     Else
                    '         Dim peter1 As Integer = 1 'Not validated....
                    '     End If
                    ' End If ''Peptide validation.
                    pept.verified = False 'Set it to some value. The real value
                    '  will be set at the end of parse, ***after*** recalibration.


                    'Changed PM_C13_CORRECTION 2007-09-12
                    If True Then 'Block. C13 correction.
                        Dim meaMass As Double = pept.measuredMass
                        Dim charge As Integer = pept.charge

                        Dim unitDiff As Integer = _
                          CInt(meaMass - pept.MascotCalculatedMass)
                        '   +0.5 not needed...
                        '   .

                        If unitDiff <> 0 Then
                            Dim C12meaMass As Double = _
                              meaMass - unitDiff * MSconstants.C12_C13_DIFF

                            'Changed PM_REFACTOR 2008-05-20
                            'Dim C12meaMCR As Double = _
                            '  (C12meaMass + _
                            '  charge * MSconstants.PROTON_MASS) / charge
                            Dim C12meaMCR As Double = _
                              PILmassCalc.chargeTransform(C12meaMass, 0, charge)

                            If unitDiff > 1 Then
                                Dim peter2 As Integer = 2
                                If pept.MascotScore > 20.0 Then
                                    Dim peter20 As Integer = 20
                                End If
                                If pept.MascotScore > 30.0 Then
                                    Dim peter30 As Integer = 30
                                End If
                            End If
                            If unitDiff < 0 Then
                                'We never expect this, at least not for
                                'the Mascot C13 feature.
                                'This can happen if precursor 
                                'mass accuracy is greater than 1 Da,
                                'e.g. 1.3 Da. E.g. HysTag sample
                                'data set.
                                Dim peter3 As Integer = 3
                            End If

                            'Replace existing values. We will lose the
                            'precursor MCR value that was in the MGF 
                            'file and thus it will be more difficult
                            'to track back.
                            pept.measuredMass = C12meaMass
                            pept.measuredMCR = C12meaMCR
                        End If
                    End If 'Block, C13 correction.


                    'Changed PM_PARSE_MEMORY_EFFICIENCY 2008-02-29
                    'Early physical exclusion.
                    Dim updateModHash As Boolean
                    Dim filteredOut2 As Boolean = _
                      PILpeptides.simpleFilteredOut( _
                        pept, parsePeptideFilter, updateModHash)
                    If Not filteredOut2 Then

                        'Changed PM_HIGHESTUNIQUELY_BADVALUES 2008-02-29
                        If peptideList Is Nothing Then
                            peptideList = New PILpeptides(numPeptMatches)
                            '  Note: capacity is only an estimate. It may be too 
                            '        high when we reject a large portion of 
                            '        the Mascot result, e.g. only including 
                            '        red peptides and/or because SILAC condition 
                            '        is not fullfilled (all sites modified 
                            '        for SILAC modification).
                            '
                            'Idea for dealing with the above:
                            '       we could detect whether or not we are 
                            '       excluding a large proportion by looking 
                            '       at the counts for the first protein. If 
                            '       we are excluding a lot then a estimate of 
                            '       the percentage excluded. This estimated 
                            '       value could even be updated as new 
                            '       proteins come in.

                            'Apply peptide filter early so e.g. the export filter (that may 
                            'be wider than the filter for preselected) does not expose 
                            'peptides that should be ignored.
                            peptideList.setPermanentPeptideFilter(parsePeptideFilter)
                        Else
                            Dim peter2 As Integer = 2
                        End If


                        'Changed PM_HIGHESTUNIQUELY_BADVALUES 2008-02-29. Add 
                        '  to the candidate list instead. The real field 
                        '  will be assigned after going through the 
                        '  peptides, effectively applying the option "Only 
                        '  highest scoring uniquely modified" to get correct 
                        '  protein score and peptides ABC counts.
                        ''Add the peptide to the protein hit.
                        ''Changed PM_REFACTOR 2006-03-16
                        ''aProtHitStru.pepts.Add(pept)
                        'aProtHitStru.peptides.addPeptide(pept)
                        peptideList.addPeptide(pept)

                        addedPeptides += 1 'For use in check after this loop.
                    Else
                        'Early filtered out! Using the simple filter.
                        Dim lowScore As Double = pept.MascotScore
                        Dim peter2 As Integer = 2
                    End If
                Else
                    'Peptide invalidated due to SILAC rule. E.g. for 
                    '  some particular quantitation mode Arg 6 and Arg10 can 
                    '  not be in the same peptide as Arg 6 and Arg10 are in
                    '  separate dishes.
                    Dim peter92 As Integer = 92
                End If
            Else
                'Peptide not in the preselected set of peptides - e.g. it
                '  is black and only red peptides were selected by the user
                '  in the options dialog.
                Dim peter91 As Integer = 91
            End If

            'Re-initialize the Hit structure.
            pept.checkboxChecked = False
            pept.verified = False
            pept.scoreInParens = False
            pept.retentionTimeEndMinutes = 0.0

            'Is this the right place to initialise the version field? No, it is not!

            resetModFields(pept.modHits2)
        Next i 'Through peptides in a parsed protein.


        'Changed PM_HIGHESTUNIQUELY_BADVALUES 2008-02-29. Moved computation of
        '  protein score and peptide counts in A,B,C to here. Otherwise they
        '  are incorrect for option "Only highest scoring uniquely modified" 
        '  as the result of this option depends on the set of peptides - all
        '  peptides must have be parsed first.
        '
        '  In fact we have postponed it even further, until the end of parse, 
        '  in setCalibratedValues(), file SDUPrecalibrator.vb.

        'Perhaps later: avoid going through the list (with all the 
        '  memory implications) if the option "Only highest scoring
        '  uniquely modified" is not in effect (e.g. all peptides
        '  are different).
        'If addedPeptides <> peptideList.peptideCount Then
        'End If

        'Changed PM_HIGHESTUNIQUELY_BADVALUES 2008-02-29.
        aProtHitStru.peptides = peptideList 'Direct 
        '  assignment for now so there is no memory 
        '  consequence either way. But we could use the 
        '  opportunity to reduce the physical size (at the 
        '  expense of some more temporary objects). E.g.
        '  if the precapacity was set too high then
        '  we get rid of it early; right after going 
        '  through the peptides for a protein.

        'Changed PM_DEFINDED_MASCOT_SORT_ORDER 2003-08-04
        'Proteins with the same score are listed after the peptide table.

        'Detect whether we have a same score section or not.

        'Changed PM_MEMORY_ALLOCATION 2004-07-29
        'Dim sameScoreArray As String() = _
        '  Regex.Split(proteinsMatchingSamePeptides, "peptides")
        Dim index1 As Integer
        Dim len1 As Integer
        Dim index2 As Integer
        Dim len2 As Integer
        'Changed PM_MEMORY_ALLOCATION_MORE_THAN_ONE_SECTION 2004-08-02
        MascotResultParser.split2( _
          proteinsMatchingSamePeptides, "peptides", _
          index1, len1, index2, len2, True)

        'Temporary, to accomodate the code below, should be changed later.
        Dim len As Integer = 2
        If len2 = 0 Then
            len = 1
        End If

        'Changed PM_MASCOT2_SUPPORT 2004-03-01
        If len = 1 Then
            'No proteins have the same score.
            Dim peter7 As Integer = 7
        Else
            'Changed PM_MASCOT2_SUPPORT 2004-03-01
            If len = 2 Then
                'One or more proteins have the same score.

                ' frmProteinList.pushToFile("C:\temp3.txt", _
                '   "************************ proteinSetStr: >>>" & proteinSetStr & "<<<")

                'Note: because of leading space before the first "<A" we
                '      ignore the first element in the array.

                'Changed PM_MEMORY_ALLOCATION 2004-07-29
                MascotResultParser.split2( _
                  proteinsMatchingSamePeptides, "<A ", _
                  index1, len1, index2, len2, True)
                'Dim proteinSetArray As String() = _
                '  Regex.Split(proteinsMatchingSamePeptides, "<A ")
                ''  the last part...

                'Changed PM_MEMORY_ALLOCATION 2004-07-29
                'Dim lenprot As Integer = proteinSetArray.GetLength(0)
                Dim lenprot As Integer = len1

                Trace.Assert(lenprot >= 2, _
                  "PIL ASSERT. Unexpected input: ." & proteinsMatchingSamePeptides)

                'Changed PM_MEMORY_ALLOCATION 2004-07-29
                'Dim someProteinStr As String = proteinSetArray(1)
                Dim someProteinStr As String = _
                  proteinsMatchingSamePeptides.Substring(index2, len2)

                Dim someProt As simpleProteinInfoStructure
                someProt.accessionNumber = Nothing 'Keep compiler happy.
                someProt.description = Nothing 'Keep compiler happy.

                'Note: this does not seem to be used at all. And why is only
                'the first protein in this list parsed? 
                'Note also that the HTML formatting, at least for Mascot 2.0,
                'is not handled properly in parseProteinInfo() - there is
                'no protein description for those proteins.
                parseProteinInfo(someProteinStr, someProt)
            Else
                Trace.Assert(True, "PIL ASSERT. Unexpected array length: len.")
            End If
        End If

        'Changed PM_PROTEINS_CHECK_SQL_PROBLEM 2003-08-04. Moved rule
        '  from "frmProteinList.vb"/setParsedProteinList().
        'Note: only the initial setting is reflected in the data
        '      structure. Any manual changes by the user is
        '      currently NOT recorded (though the export function reads
        '      directly off the visual structure).
        '
        '      Has this bug been corrected yet????

        'Changed PM_MARKER_POSSIBLE_BUG 2007-08-31


        'Changed PM_VALIDATION_AFTER_RECALIBRATION 2007-09-24. Had to be moved 
        '  until after recalibration as peptide validation depends calibrated
        '  peptide mass.
        '
        ' If True Then
        '     Dim valueToSet As Boolean = False
        ' 
        '     'Possible rounding problem when we use double.
        '     Dim protScore As Double = aProtHitStru.scoreInABC
        '     protScore += 0.0001 'Margin for the "=" below.
        ' 
        '     If protScore >= _
        '        mParseOptions.protDefaultValidationScoreThr Then
        ' 
        '         'Changed PM_PROTEINVAL_REQUIRES_PEPTIDEVALS 2007-08-31. Added this
        '         '  extra requirement.
        '         If verifiedPeptides > 0 Then
        '             valueToSet = True
        '         Else
        '             Dim peter2 As Integer = 2 'Enough peptides except for very
        '             '  low scoring ones, but none of them were validated.
        '         End If
        '     Else
        '         Dim peter60 As Integer = 60 'Sum of peptide
        '         '  scores (above some low threshold) not high enough.
        '     End If
        '     aProtHitStru.proteinHasBeenChecked = valueToSet
        ' End If


        ''For consistency check.
        'If Not aProtHitStru.MascotTotalPepts = numPepts Then
        '    'Changed PM_NEWMASCOT2_FORMAT 2004-06-17.
        '    'Disabled because not all peptides may be listed for Mascot 2.xx 
        '    'and later.
        '    'MsgBox("problem with total number of peptides")
        'End If
        'If Not aProtHitStru.MascotTotalScore = totalScore Then
        '    'MsgBox("problem with total peptide score")
        'End If

    End Sub 'ParseOneProteinHitTable


    'Notes:
    '  The 2 string parameters: meant as const ByRef
    '  Parameter aPeptHitStru: out parameter that may be left untouched! 
    '  Better
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Private Shared Sub modificationParseMatch(ByRef aStr As String, _
      ByRef aMatchStr As String, ByRef aModCount As Integer)

        'Changed PM_TRIPLE_LYSINE_MATCH_PROBLEM 2003-12-01
        'Note: if parentheses should be matched, e.g. "(R-full)", then they
        '      should be escaped at the client side! - e.g. "\(R-full\)".

        'Changed PM_MEMORY_ALLOCATION_MODMATCHSTR 2004-07-29. We now expect
        'that this has been prepared already at program startup such
        'the passed string already contains "\s*(\d*)\s*".
        'Dim regStr As String = "\s*(\d*)\s*" & aMatchStr
        'Dim result As Match = Regex.Match(aStr, regStr)
        Dim result As Match = Regex.Match(aStr, aMatchStr)

        If result.Success Then
            If IsNumeric(result.Groups(1).Value) Then
                aModCount = CInt(result.Groups(1).Value)
            Else
                aModCount = 1
            End If
        Else
            'Why not set to 0 if no match?
        End If
    End Sub 'modificationParseMatch


    '****************************************************************************
    '*  SUBROUTINE NAME:   updateCountForModification                           *
    '*  Purpose: <general description>.                                         *
    '*                                                                          *
    '****************************************************************************
    Private Sub updateCountForModification( _
      ByRef anOutModHits2 As Generic.List(Of modificationCountStruct), _
      ByVal aQuantModificationID As Integer, _
      ByVal aHits As Integer)

        'Old:
        '  ByRef anOutModHits As ArrayList

        Dim found As Boolean = False

        Dim lastIndex As Integer = anOutModHits2.Count - 1
        Dim j As Integer

        'First see if we already have the modification in the peptide's list.
        For j = 0 To lastIndex
            Dim curItem As modificationCountStruct = anOutModHits2(j)
            If curItem.quantModificationID = aQuantModificationID Then
                curItem.count3 += aHits
                anOutModHits2(j) = curItem 'Write-back.
                found = True
                Exit For
            End If
        Next j

        If Not found Then
            'Then insert new item.
            Dim curItem As modificationCountStruct
            curItem.count3 = aHits
            curItem.quantModificationID = aQuantModificationID
            anOutModHits2.Add(curItem)
        Else
            Dim peter2 As Integer = 2 'Would this even happen under normal
            '  circumstances? For two modifications where one has a more
            '  specific match-string?
        End If
    End Sub 'updateCountForModification


    '****************************************************************************
    '*  SUBROUTINE NAME:   removeHTMLtags                                       *
    '*  Purpose: <general description>.                                         *
    '*                                                                          *
    '****************************************************************************
    Private Sub removeHTMLtags( _
      ByRef aInOutStr As String, ByVal aStartIndex As Integer)

        Dim capacity As Integer = aInOutStr.Length - aStartIndex
        Dim noTagsSB As StringBuilder = New StringBuilder(capacity)

        Dim isInTag As Boolean = False
        Dim done As Boolean = False
        Dim curIndex As Integer = aStartIndex
        Dim copyStart As Integer = aStartIndex
        While Not done
            If isInTag Then
                'State 1
                Dim index As Integer = aInOutStr.IndexOf(">", curIndex)
                If index >= 0 Then
                    copyStart = index + 1
                    curIndex = index + 1
                    isInTag = False
                Else
                    'Then the tag is not complete. We don't need to do anything
                    done = True
                End If
            Else
                'State 2
                Dim index As Integer = aInOutStr.IndexOf("<", curIndex)
                If index >= 0 Then
                    curIndex = index + 1
                    isInTag = True
                Else
                    'The rest of the string is normal text.
                    index = aInOutStr.Length
                    done = True
                End If

                Dim copyLen As Integer = index - copyStart
                If copyLen > 0 Then
                    noTagsSB.Append(aInOutStr, copyStart, copyLen)
                End If
            End If
        End While

        aInOutStr = noTagsSB.ToString
    End Sub 'removeHTMLtags


    '****************************************************************************
    '*  SUBROUTINE NAME:   extractNextTrimmed                                   *
    '*  Purpose: <general description>.                                         *
    '*                                                                          *
    '****************************************************************************
    Private Function extractNextTrimmed( _
      ByRef anInStr As String, ByVal aScanIndex2 As Integer, _
      ByRef anOutNewScanIndex As Integer, _
      ByVal aPeptideSequencePart As Boolean) _
      As String

        'Changed PM_MASCOT22 2007-04-10. Use more robust algorithm. No
        '  longer assume the values are followed by one " " and then
        '  by one or more spaces. We will now accept any number of " "
        '  and any number of spaces.


        ' Dim nextIndex As Integer = anInStr.IndexOf(" ", aScanIndex)
        ' If nextIndex < 0 Then
        '     nextIndex = anInStr.Length
        ' End If
        ' anOutNewScanIndex = nextIndex + 6 '6: length of " ".
        ' 
        ' Dim startIndex As Integer = aScanIndex
        ' While anInStr.Chars(startIndex) = " "
        '     startIndex += 1
        ' End While
        ' 
        ' Dim endIndex As Integer = nextIndex - 1
        ' While anInStr.Chars(endIndex) = " "
        '     nextIndex -= 1
        ' 
        '     'Changed PM_MASCOT22 2007-04-10
        '     Trace.Assert(nextIndex >= startIndex, _
        '       "PIL ASSERT. nextIndex < startIndex.")
        ' 
        ' End While
        ' 
        ' Dim len As Integer = endIndex - startIndex + 1 '+1 because endIndex is inclusive.
        ' Trace.Assert(len > 0, _
        '   "PIL ASSERT. Empty string in extractNextTrimmed(). From index " & _
        '   aScanIndex & " in this string: " & anInStr)


        'Go past any leading space. This is required. We assume there
        'will be no leading " "...
        Dim index As Integer = aScanIndex2
        While anInStr.IndexOf(" ", index, 1) >= 0
            index += 1
        End While

        'Find end of content.
        Dim inStrLen As Integer = anInStr.Length()
        Dim contentEndIndex As Integer = inStrLen 'Default, if at end.
        If Not aPeptideSequencePart Then
            Dim index1 As Integer = anInStr.IndexOf(" ", index)
            If index1 < 0 Then
                index1 = 999999
            End If

            Dim index2 As Integer = anInStr.IndexOf(" ", index)
            If index2 < 0 Then
                index2 = 999999
            End If

            'Find minimum of the two, first " " or " " is sought.
            contentEndIndex = index1
            If index2 < contentEndIndex Then
                contentEndIndex = index2 'This means a space comes 
                '  before " ". This is unusual...
            End If

            If contentEndIndex = 999999 Then
                Trace.Assert(False, "PIL ASSERT. This can not happen...")
            End If
        End If

        Dim rlen As Integer = contentEndIndex - index

        Dim index3 As Integer = contentEndIndex
        Dim done As Boolean = index3 = inStrLen
        While Not done
            If anInStr.IndexOf(" ", index3, 1) >= 0 Then
                index3 += 1
            Else
                'Changed PM_MASCOT22_OLDERFORMATS 2007-04-12.
                'Note: IndexOf() does not check if there are
                '      enough characters left in the string, in
                '      this case 6. Therefore we must 
                '      perform this test ourselves.
                Dim charsLeft As Integer = inStrLen - index3

                If charsLeft < 6 Then
                    Dim peter6 As Integer = 6 'For breakpoints.
                End If

                'Relies on short-curcuit boolean:
                If charsLeft >= 6 AndAlso _
                   anInStr.IndexOf(" ", index3, 6) >= 0 Then
                    index3 += 6
                Else
                    done = True
                End If
            End If
        End While
        anOutNewScanIndex = index3
        Return anInStr.Substring(index, rlen)
    End Function 'extractNextTrimmed


    '****************************************************************************
    '*  SUBROUTINE NAME:   extractPeptideNumber                                 *
    '*  Purpose: <general description>.                                         *
    '*                                                                          *
    '****************************************************************************
    Private Function extractPeptideNumber( _
      ByRef anInStr As String, ByVal aScanIndex As Integer, _
      ByRef aOutNumber As Double, ByRef anErrorMsg As String) As Integer

        Dim newIndex As Integer
        Dim numberStr As String = _
          extractNextTrimmed(anInStr, aScanIndex, newIndex, False)
        If IsNumeric(numberStr) Then
            aOutNumber = CDbl(numberStr)
        Else
            MsgBox(anErrorMsg & ControlChars.NewLine & anInStr)
        End If
        Return newIndex
    End Function 'extractPeptideNumber


    '****************************************************************************
    '*  SUBROUTINE NAME:   ParsePeptMatch                                       *
    '*  Purpose: <general description>.                                         *
    '*                                                                          *
    '****************************************************************************
    Private Sub ParsePeptMatch(ByRef aStr As String, _
      ByRef aPeptHitStru As PeptideHitStructure, _
      ByVal aUseMod As Boolean)

        'This is the relevant line in peptide table with missed cleavages
        'peptide score in parentesis or not and rank.
        ';1   (35)    1 
        'missed cleavages, three HTML tabs, score, four tabs, rank
        'just do two alternative matches for the case with or without ()

        'there are a number of cases which we need to treat differently:
        'the peptide could be in bold or not bold
        'the peptide could be in red or black
        'the peptide could have a checked checkbox or not
        'the score could be in parentheses or not
        'the peptide sequence could be followed by modification or not

        'Changed PM_MEMORY_ALLOCATION 2004-07-28
        'Dim origStr As String = aStr 'For debugging

        Dim matchSubStr As String
        Dim result As Match

        'Changed PM_VERSIONFIELD 2003-02-13
        aPeptHitStru.version = 100 'Vers. 1.00.  Is this a good place to
        '  initialise it?

        'first extract the elution time in minutes from the 'tool tip'
TODO:   'Extract elution time 
        'example for 53.08 to 53.08 period 0 experiment 4 cycle  1
        'title(Elution%20from%3a%2053%2e08%20to%2053%2e08%20%20%20period%3a%200%20%20%20experiment%3a%204%20cycles%3a%20%201%20%20) query(2421)"
        'Different strategy: extract this from the tool tip at the bottom of the page
        '
        Try
            'Changed PM_MARKER_NOELUTIONFORBLACKPEPTIDES 2007-12-14
            'Note: the retention time information in the peptide line is ***only*** available 
            '      for checked peptides (e.g. a black peptide does not have the 
            '      information!!! -it is in the tooltips however)

            'Note backslash before parentheses.
            result = Regex.Match(aStr, "title\(Elution(.+?)query\(")
            If result.Success Then
                matchSubStr = result.Groups(1).Value

                'Changed PM_RET_OVERWRITE 2003-11-18
                ''Changed PM_FINNEGAN_RETENTION_TIME 2003-11-18
                ''This will only be in some files, not all.
                'Dim spectrumNum As Integer = -1
                'result = Regex.Match(matchSubStr, "FinneganScanNumber\%3a(?:\%20)+(.+)\)")
                'If result.Success Then
                '    spectrumNum = CInt(result.Groups(1).Value)
                'End If
                'aPeptHitStru.spectrumNum = spectrumNum


                'Note: effectively we only match the first, start retention
                '      time (e.g. "from%3a%20777%2e777%20to").
                '
                '      2 or 3 other things match the regular expression below, 
                '      the end retention time ("to%20777%2e777%20") and, for
                '      newer versions of DTASuperCharge, the precursor
                '      intensity in "precIntensity%3a%2036223%2e0%20".

                result = Regex.Match(matchSubStr, "%20(\d+)%2e(\d+)")
                If result.Success Then
                    Dim elutStr As String = _
                      result.Groups(1).Value & "."c & result.Groups(2).Value

                    If False Then 'If True: for debugging only. -it did not work as expected...
                        Dim end1 As String = result.Groups(2).Value
                        Dim end2 As String = result.Groups(3).Value

                        Dim precIntensity1 As String = result.Groups(4).Value
                        Dim precIntensity2 As String = result.Groups(5).Value

                        Dim peter2 As Integer = 2
                    End If

                    If IsNumeric(elutStr) Then
                        'Why are these assignments repeated below??

                        '*** Note ***: these 2 assignments seems to have no 
                        'effect as the fields are overwritten by the values
                        'from .startElutionTime below.....
                        'Those values are derived in ParseToolTips() and with
                        'easier parsing.

                        Dim retT As Double = CDbl(elutStr)
                        aPeptHitStru.retentionTimeStartMinutes = retT 'For
                        '  backward compatibility still put it in here.

                        'Changed PM_LC_PEAKDETECTION 2003-03-20
                        aPeptHitStru.MSMSretentionTimeMinutes = retT
                    Else
                        MsgBox("couldn't get the elution time" & vbCrLf & aStr)
                    End If
                End If
            Else
                'E.g. for blackpeptides.
                Dim peter2 As Integer = 2 'Bad! Not matched: "title\(Elution(.+?)query\("...
            End If
        Catch
            MsgBox( _
              "Could not extract elution time and experiment" & vbCrLf & aStr)
            Exit Sub
        End Try

        'Now check if we have a checked checkbox.

        If aStr.IndexOf("checkbox") >= 0 Then
            aPeptHitStru.checkboxChecked = True
        End If

        'Note: this block ***must*** be after the "title\(Elution(.+?)query\(" matching (unless
        '      we change it so it is possible) because both affect variable "result" that we 
        '      use later to advance where to parse from (red, bold, start position of
        '      peptide table information, etc.).
        If True Then
            'Then extract the query number from the end of the query number
            'anchor, which is the first column - like this >2080</A>.
            result = Regex.Match(aStr, ">(\d+)</A>")
            If result.Success Then
                matchSubStr = result.Groups(1).Value
                If IsNumeric(matchSubStr) Then
                    aPeptHitStru.queryNumber = CInt(matchSubStr)
                Else
                    MsgBox("No valid query number " & vbCrLf & aStr)
                    Exit Sub
                End If
            Else
                MsgBox("Could not find query number " & vbCrLf & aStr)
                Exit Sub
            End If
        End If



        'Changed PM_NEWMASCOT2_FORMAT 2004-06-17
        'Dim effectiveIndex As Integer = aPeptHitStru.queryNumber - 1
        Dim effectiveIndex As Integer

        'Changed PM_NEWMASCOT2_FORMAT 2004-06-17
        'Starting. For now we do a linear search for the query. Is this too slow?
        'Otherwise we could use a hash.
        Dim foundQ As Boolean = False
        Dim lastIndex As Integer = mTtQueryArr.Length - 1
        Dim j As Integer
        For j = 0 To lastIndex
            If mTtQueryArr(j).queryNo = aPeptHitStru.queryNumber Then
                effectiveIndex = j
                foundQ = True
                Exit For
            End If
        Next j
        If Not foundQ Then
            MsgBox("Query number " & aPeptHitStru.queryNumber & "not found.")
        End If

        'Assign the values from the Query structure.
        With mTtQueryArr(effectiveIndex)
            'Why are these assignments repeated above??

            'Changed PM_LC_PEAKDETECTION 2003-03-20
            aPeptHitStru.retentionTimeStartMinutes = .startElutionTime 'For
            '  backward compatibility still put it in here.
            aPeptHitStru.MSMSretentionTimeMinutes = .startElutionTime

            'Changed PM_FINNEGAN_RETENTION_TIME 2003-11-18
            aPeptHitStru.spectrumNumber = .spectrNumb

            'Changed PM_PRECURSOR_INTENSITY 2005-09-08
            aPeptHitStru.precursorIntensity = .precursorIntensity

            aPeptHitStru.period2 = .period2
            aPeptHitStru.experimentNumber = .experimentNumber
            aPeptHitStru.cycle = .cycle
            aPeptHitStru.firstScore = .score1
            aPeptHitStru.firstDeltaScore = .score1 - .score2 'We don't need this.

            'Changed PM_GENERALISED_QUANT_MODE_MODLOCATION_MARKER 2003-12-08
            'Later....
            'aPeptHitStru.modHit.modLocFirstSeq = .modLocSeq1

            'Changed PM_STRING_CLEANUP 2004-12-14
            'If .seq2.IndexOf("<") > 0 Then
            '    aPeptHitStru.secSequence = Regex.Replace(.seq2, "<.*?>", "")
            'Else
            '    aPeptHitStru.secSequence = .seq2
            'End If

            aPeptHitStru.secScore = .score2

            'Changed PM_GENERALISED_QUANT_MODE_MODLOCATION_MARKER 2003-12-08
            'Later....
            'aPeptHitStru.modHit.modLocSecSeq = .modLocSeq2

            aPeptHitStru.seq1 = .seq1 'these are still with formatting
            aPeptHitStru.seq2 = .seq2
            aPeptHitStru.seq1Unique = .seq1Unique
            aPeptHitStru.seq2Unique = .seq2Unique

            'Changed PM_SEVERALWIFFS 2003-08-26
            aPeptHitStru.rawFileID = .qRawFileID

            'Changed PM_PEPT_RAWFILE_PATH 2003-11-05
            aPeptHitStru.rawFileFullPath = _
              rawDataFileHandling.getFullRawFilePath(mRawFiles, .qRawFileID)
        End With

        'Changed PM_MEMORY_ALLOCATION 2004-08-01
        'General for this section: set a starting index instead of
        'copying strings.

        'Changed PM_MEMORY_ALLOCATION 2004-08-01
        ''We don't need the first part of the string, so we cut it to
        ''the end of the anchor
        'aStr = aStr.Remove(0 , result.Index + result.Length)
        ''Missing: something for very light red peptide.
        Dim startIndex As Integer = result.Index + result.Length

        'Now we have some   and then the colour or not.

        Dim isRed, isBold As Boolean
        'We determine if the peptide is bold and red. Then we remove leading
        '" " so that the string in all cases will start with the measured
        'peptide mass.

        Dim redIndex As Integer = aStr.IndexOf("color=#ff0000>", startIndex)
        If redIndex >= 0 Then
            isRed = True 'its a red peptide

            'Changed PM_MEMORY_ALLOCATION 2004-08-01
            'aStr = aStr.Remove(0, redIndex + 14)
            startIndex = redIndex + 14
        End If

        Dim boldIndex As Integer = aStr.IndexOf("<B>", startIndex)
        If boldIndex >= 0 Then
            isBold = True 'it's a bold peptide

            'Changed PM_MEMORY_ALLOCATION 2004-08-01
            'aStr = aStr.Remove(0, boldIndex + 3)
            startIndex = boldIndex + 3
        End If

        If isBold Then
            If isRed Then
                aPeptHitStru.MascotColour = _
                  mascotColourEnum.enumBoldRed
            Else
                aPeptHitStru.MascotColour = _
                  mascotColourEnum.enumBoldBlack
            End If
        Else
            If isRed Then
                aPeptHitStru.MascotColour = _
                  mascotColourEnum.enumLightRed
            Else
                aPeptHitStru.MascotColour = _
                  mascotColourEnum.enumLightBlack
            End If
        End If

        'Now the string should start with   or with the measured MCR
        'remove any possible leading non breaking spaces.
        'Do While aStr.StartsWith(" ")
        Do While aStr.IndexOf(" ", startIndex) = startIndex
            'Changed PM_MEMORY_ALLOCATION 2004-08-01
            'aStr = aStr.Remove(0, 6)
            startIndex += 6
        Loop

        'Changed PM_MASCOT2_SUPPORT 2004-03-01. Now below.
        ' 'now we extract the measured peptide mass which extends to
        ' 'the next 'space'
        ' matchSubStr = aStr.Substring(0, aStr.IndexOf(" "))
        ' If IsNumeric(matchSubStr) Then
        '     aPeptHitStru.measuredMZ = CDbl(matchSubStr)
        ' Else
        '     MsgBox("Problem with extracting measured MCR" & vbCrLf & aStr)
        ' End If

        'Changed PM_MASCOT2_SUPPORT 2004-03-01.
        'Filter out all HTML tags first, otherwise the following will
        'not work for Mascot 2.0.
        If True Then
            'Use some substitition pattern here instead????

            'Changed PM_MARKER_MEMORY_ALLOCATION 2004-07-30
            'Use capacity for StringBuilder and/or HTML tag eliminator

            'Changed PM_MEMORY_ALLOCATION 2004-08-01
            ' Dim parts1 As String() = _
            '   Regex.Split(aStr, "<[^>]+>")
            ' 
            ' 'Changed PM_MEMORY_PROBLEM 2004-04-14
            ' 'Dim filteredItems As String = ""
            ' Dim filteredItemsSB As StringBuilder = New StringBuilder
            ' 
            ' Dim pepItem As String
            ' For Each pepItem In parts1
            '     'Changed PM_MEMORY_PROBLEM 2004-04-14
            '     filteredItemsSB.Append(pepItem)
            ' Next
            ' 
            ' 'Changed PM_MEMORY_PROBLEM 2004-04-14
            ' 'aStr = filteredItems
            ' aStr = filteredItemsSB.ToString
            Me.removeHTMLtags(aStr, startIndex)
        End If

        'Now we extract items between 'spaces', we require that
        'something different to   is between them.
        'Changed PM_MASCOT2_SUPPORT 2004-03-01
        'Dim resultsCol As MatchCollection = _
        Dim done As Boolean = False
        While Not done
            Dim oldSize As Integer = aStr.Length

            'Changed PM_MEMORY_ALLOCATION 2004-08-01
            If aStr.IndexOf("  ") >= 0 Then
                aStr = aStr.Replace("  ", " ")
            End If

            Dim newSize As Integer = aStr.Length
            If newSize = oldSize Then
                done = True
            End If
        End While

        done = False
        While Not done
            Dim oldSize As Integer = aStr.Length

            'Changed PM_MEMORY_ALLOCATION 2004-08-01
            If aStr.IndexOf(" +") >= 0 Then
                aStr = aStr.Replace(" +", " +")
            End If

            If aStr.IndexOf("+ ") >= 0 Then
                aStr = aStr.Replace("+ ", "+ ")
            End If

            Dim newSize As Integer = aStr.Length
            If newSize = oldSize Then
                done = True
            End If
        End While

        'Measured MW; calculated MW; delta; missed cleavages;
        'score (w or w/o parens) rank; sequence.

        Dim seqPlusMods As String = Nothing 'Keep compiler happy.
        If True Then
            Dim items2 As Integer = 0
            If True Then
                Dim done2 As Boolean = False
                Dim index5 As Integer = 0

                'Changed PM_MASCOT22_MORE_TROUBLE 2007-04-19
                ' 'Changed PM_MASCOT22_OLDERFORMATS 2007-04-12
                ' 'Detect older formats.
                ' Dim searchMarker As String = Nothing
                ' If aStr.IndexOf(mParseMarker_New, 0) >= 0 Then
                '     searchMarker = mParseMarker_New
                ' Else
                '     searchMarker = mParseMarker_Old 'Older format.
                ' End If
                ' 
                ' While Not done2
                '     'Changed PM_MASCOT22_OLDERFORMATS 2007-04-12
                '     ''Changed PM_MASCOT22 2007-04-11. We now rely on some spaces
                '     ''  after " " and that the extra " " in front of
                '     ''  the sequence is ***not*** followed by a space...
                '     ''Dim nextIndex As Integer = aStr.IndexOf(" ", index5)
                '     'Dim nextIndex As Integer = aStr.IndexOf("  ", index5)
                '     Dim nextIndex As Integer = aStr.IndexOf(searchMarker, index5)
                ' 
                '     If nextIndex > 0 Then
                '         items2 += 1
                '         index5 = nextIndex + 1
                '     Else
                '         items2 += 1 'For the last part after the last " ".
                '         done2 = True
                '     End If
                ' End While

                Dim inInWhiteSpace As Boolean = True 'Whitespace in this
                '  case is " " and " ".

                While Not done2
                    Dim nextIndex1 As Integer = aStr.IndexOf(" ", index5)
                    Dim nextIndex2 As Integer = aStr.IndexOf(" ", index5)

                    Dim nextIsWhiteSpace As Boolean = _
                      nextIndex1 = index5 Or nextIndex2 = index5

                    If nextIndex1 < 0 Then 'We expect at least one " " between the columns.
                        'State change
                        inInWhiteSpace = False
                        items2 += 1

                        done2 = True
                    Else
                        'State machine
                        If inInWhiteSpace Then
                            If nextIsWhiteSpace Then
                                'Find which kind of white space is first.

                                'If nextIndex1 < 0 Then
                                '    nextIndex1 = 999999
                                'End If
                                If nextIndex2 < 0 Then
                                    nextIndex2 = 999999
                                End If

                                ' +1: step over - IndexOf() returns index for head...
                                If nextIndex1 < nextIndex2 Then
                                    index5 = nextIndex1 + 6 ' " " is first
                                Else
                                    index5 = nextIndex2 + 1 ' " " is first
                                End If
                            Else
                                index5 += 1 'Note: this does not step over a
                                '  trailing " ", but we are only after
                                '  finding the number of columns.

                                'State change
                                inInWhiteSpace = False
                                items2 += 1
                            End If
                        Else
                            'In content. Skip to next " " - " " is allowed in the content.

                            'For test only.
                            Dim effectiveIndex5 As Integer = index5 - 1 '1 because 1 was 
                            '  added to step forward for the next string search.
                            Dim cLen As Integer = nextIndex1 - effectiveIndex5
                            Dim approxContent As String = aStr.Substring(effectiveIndex5, cLen)

                            'State change
                            inInWhiteSpace = True

                            index5 = nextIndex1  'Note: nextIndex1 is guaranteed to be >= 0.
                        End If
                    End If
                End While 'Finding number of columns.
            End If 'Block, finding number of columns.

            If Not items2 >= 6 Then '7 in case of modification
                MsgBox( _
                  "could not extract 6 columns from peptide hit row" & _
                  vbCrLf & aStr)
            End If

            If True Then 'True: for debugging only.
                If aStr.IndexOf("557.246549") > 0 Then
                    Dim peter7 As Integer = 7
                End If
                If aStr.IndexOf("558.777057") > 0 Then
                    Dim peter8 As Integer = 8
                End If
            End If


            Dim scanIndex As Integer = 0
            scanIndex = Me.extractPeptideNumber( _
              aStr, scanIndex, aPeptHitStru.measuredMCR, _
              "Problem with extracting measured MCR")

            scanIndex = Me.extractPeptideNumber( _
              aStr, scanIndex, aPeptHitStru.measuredMass, _
              "problem extracing peptide neutral mass")

            scanIndex = Me.extractPeptideNumber( _
              aStr, scanIndex, aPeptHitStru.MascotCalculatedMass, _
              "problem extracing Mascot calculated neutral mass")

            scanIndex = Me.extractPeptideNumber( _
              aStr, scanIndex, aPeptHitStru.deltaMass, _
              "problem extracing delta mass")

            'Extract it double
            Dim missedD As Double
            scanIndex = Me.extractPeptideNumber( _
              aStr, scanIndex, missedD, _
              "problem extracing missed cleavages")
            Dim missed As Integer = CInt(missedD)
            aPeptHitStru.missedCleavages = missed

            'Changed PM_REDUCTORSCRIPT_SUPPORT 2007-12-17
            Trace.Assert(missed < 10, _
              "PIL ASSERT. Missed cleavages probably too high: " & _
              missed & ".")

            matchSubStr = _
              extractNextTrimmed(aStr, scanIndex, scanIndex, False)
            If matchSubStr.Chars(0) = "("c Then
                aPeptHitStru.scoreInParens = True
                matchSubStr = matchSubStr.Trim("("c, ")"c, " "c) 'To trim with
                aPeptHitStru.MascotScore = CInt(matchSubStr)
            Else
                aPeptHitStru.scoreInParens = False
                aPeptHitStru.MascotScore = CInt(matchSubStr)
            End If

            If True Then
                '6 items extracted at this point
                Dim jumpOverCount As Integer = items2 - (6 + 2)

                Dim lastIndex2 As Integer = jumpOverCount - 1
                Dim i As Integer
                For i = 0 To lastIndex2
                    matchSubStr = _
                      extractNextTrimmed(aStr, scanIndex, scanIndex, False)
                Next i
            End If

            'Extract it as double.
            Dim rankD As Double
            scanIndex = Me.extractPeptideNumber( _
              aStr, scanIndex, rankD, "problem extracing rank")
            aPeptHitStru.rank = CInt(rankD)

            seqPlusMods = _
              extractNextTrimmed(aStr, scanIndex, scanIndex, True)

            'Changed PM_MASCOT22 2007-04-11
            'Note: it seems that "<U>" and "</U>" have already been stripped
            '      at this point - the expression below always evaluate
            '      to zero. Is that expected?
            '
            '      Probably it is because removeHTMLtags() removes them.
            '
            If seqPlusMods.IndexOf("<U>", 0) >= 0 Then 'Detect it first to
                '  avoid unnecessary memory operations.

                seqPlusMods = Regex.Replace(seqPlusMods, "<.*?>", "")
            End If
        End If

        'Changed PM_PEPTIDE_POSITION 2006-06-22
        'Note: the below will break if modification 
        '      name contains ".", "," or "-" ...
        'Maybe we should make it more robust and use the "result" variable 
        'below in the "else" branch to filter out the modifications?

        'Changed PM_MASCOT21 2005-06-12
        Dim dotIdx As Integer = seqPlusMods.IndexOf(".") 'Use of
        '  seqPlusMods assumes that there is nothing before the sequence
        '  information - like white space.
        If dotIdx = 1 Then
            'Mascot version 2.1 and later.

            Dim startIdx As Integer = dotIdx + 1
            Trace.Assert(startIdx = 2, _
              "PIL ASSERT. startIdx is not 2, " & startIdx & ".")

            'At this point we are sure there is a dot in the sequence string.
            Dim endIdx As Integer = seqPlusMods.IndexOf(".", startIdx)
            Dim seqLen As Integer = endIdx - startIdx
            aPeptHitStru.AASequence = _
              seqPlusMods.Substring(startIdx, seqLen)  '2 is first character after the dot...

            'Changed PM_PEPTIDE_POSITION 2006-06-22. Disabled. We can no longer 
            'assume that the last two characters are "." and the N-terminal AA.
            'If True Then 'For Assert. If evaluating "result.Groups(0).Value" is
            '    '  expensive (e.g. memory garbage) then it can be turned off.
            '    Dim lastIndexSPM As Integer = result.Groups(0).Value.Length - 1
            '    Dim expectedLastIndex As Integer = startIdx + seqLen + 1
            '    Trace.Assert(lastIndexSPM = expectedLastIndex, _
            '      "PIL ASSERT. Last index not the expected. Full seq: " & _
            '      (seqPlusMods) & _
            '      ". Using seq: " & result.Groups(0).Value)
            'End If

            'Dim leftFr As String = _
            '  result.Groups(0).Value.Substring(0, 1) 
            aPeptHitStru.leftFlankAA = _
              CShort(AscW(seqPlusMods.Substring(0, 1))) '0: startIdx - 2, assured by
            '   the assert above.

            'Dim rightFr As String = _
            '  result.Groups(0).Value.Substring(startIdx + seqLen + 1, 1)
            'Dim e1 As Integer = AscW(rightFr)
            aPeptHitStru.rightFlankAA = _
              CShort(AscW(seqPlusMods.Substring(startIdx + seqLen + 1, 1)))
            'CChar()

            If True Then 'For debugging only
                If aPeptHitStru.leftFlankAA = AscW("-") Then
                    Dim peter3 As Integer = 3 'Peptide at protein N-terminal.
                End If
                If aPeptHitStru.rightFlankAA = AscW("-") Then
                    Dim peter4 As Integer = 4 'Peptide at protein C-terminal.
                End If
            End If

            'Changed PM_PEPTIDE_POSITION 2006-06-22
            If True Then
                Dim peptideStartPos As Integer = -1
                Dim peptideEndPos As Integer = -1

                Dim startIndex2 As Integer = _
                  seqPlusMods.IndexOf(",", endIdx) 'This depends on local
                '   changes to the Mascot server...
                If startIndex2 >= 0 Then

                    Dim startIndex3 As Integer = _
                      seqPlusMods.IndexOf("-", startIndex2)

                    If startIndex3 >= 0 Then
                        Dim startPosStrStart As Integer = startIndex2 + 1
                        Dim len2 As Integer = _
                          startIndex3 - startPosStrStart

                        'Dim startPosStr As String = _
                        '  seqPlusMods.Substring(startPosStrStart, len2)
                        peptideStartPos = _
                          CInt(seqPlusMods.Substring(startPosStrStart, len2))

                        Dim endPosStrStart As Integer = _
                          startIndex3 + 1

                        Dim startIndex4 As Integer = _
                          seqPlusMods.IndexOf(" ", startIndex3)

                        Dim endPosStrEnd As Integer = _
                          startIndex4
                        If startIndex4 >= 0 Then
                            Dim peter4 As Integer = 4
                        Else
                            'For peptides without modifications.
                            endPosStrEnd = seqPlusMods.Length
                        End If

                        Dim len3 As Integer = _
                          endPosStrEnd - endPosStrStart

                        'Dim endPosStr As String = _
                        '  seqPlusMods.Substring(endPosStrStart, len3)
                        peptideEndPos = _
                          CInt(seqPlusMods.Substring(endPosStrStart, len3))

                    End If ' "-" exists
                Else
                    'No peptide position information...
                    Dim peter8 As Integer = 8
                End If

                aPeptHitStru.startPositionInProtein = peptideStartPos
                aPeptHitStru.endPositionInProtein = peptideEndPos

            End If 'Block.
        Else
            'We are here for older versions of Mascot (before version 2.1) where
            'there are not flanking amino acids...

            'Changed PM_PEPTIDE_POSITION 2006-06-22. Moved down here
            'because we don't use it in the block above (and not
            'below either).

            'Changed PM_STANDARDS_COMPLIANCE 2005-10-20. Now also accepts
            '  the coding for protein terminal, "-". This bug had no
            '  consequence before as we were ignoring the flanking AAs
            '  and just picked what was between the dots...
            ''Changed PM_MASCOT21 2005-06-12
            'd$ Changed PM_MASCOT2_SUPPORT 2004-03-01
            ''result = Regex.Match(seqPlusMods, "[A-Z]+") 'Strip modifications
            'result = Regex.Match(seqPlusMods, "[A-Z\.]+") 'Strip modifications

            '  part. But will it now fail if modification contained a word 
            '  with all capital letters??
            '  Perhaps it would be better to break on the "+" sign?

            'For debugging only, setting breakpoint for a variable modifications.
            If result.Groups.Count > 1 Then
                Dim peter1 As Integer = 1
            End If

            'result = Regex.Match(seqPlusMods, "[A-Z\.\-]+") 'Strip modifications
            result = Regex.Match(seqPlusMods, "[A-Z\.\-\,0-9]+") 'Strip modifications.

            aPeptHitStru.AASequence = result.Groups(0).Value 'When do we ever here? For
            '  Mascot versions older than v. 2.1.

            'Changed PM_STANDARDS_COMPLIANCE 2005-10-20
            aPeptHitStru.leftFlankAA = CShort(AscW(" ")) '42? -no 32!
            aPeptHitStru.rightFlankAA = CShort(AscW(" "))
        End If

        'Changed PM_CYS_TROUBLE 2003-11-14
        'd$ Changed PM_REFACTOR_GLOBALS 2003-10-09
        ''Changed PM_NOMODS_MASS 2003-10-08
        'Note: no modifications!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        'aPeptHitStru.calculatedMassNoMods = _
        '  MMaaSequence.monoMass(aPeptHitStru.AASequence, "")
        aPeptHitStru.calculatedMassNoMods = _
          MMaaSequence.monoMass(aPeptHitStru.AASequence, "noCysMod")

        'Changed PM_MEMORY_ALLOCATION 2004-08-01
        'Moved down here..
        'MM added 23Oct2002 with calculated and measured MW we can assign
        'the(charge).
        'ToDo: remove all the ad hoc charge calculations in the code.
        aPeptHitStru.charge = _
          CInt(aPeptHitStru.MascotCalculatedMass / _
               aPeptHitStru.measuredMCR + _
               0.2)

        Trace.Assert(aPeptHitStru.version > 0, _
          "PIL ASSERT. Uninitialised value, aPeptHitStru.version")

        'Changed PM_PROPER_GOOD_PEAK_INIT 2003-04-16
        'It would be better to have this in some kind of constructor instead.
        aPeptHitStru.goodMSpeak = True

        'Changed PM_BADPEAKREASON_BUG 2003-09-26
        aPeptHitStru.badPeakReason = vbTab 'Because an error string contains 
        '  a TAB and that columns must align in the Save/Export,
        'in NakedPeptideTable(), QuantWindow.vb.

        'Changed PM_VERY_SERIOUS_PARSING_BUG 2003-10-09
        'Note: we must reset because the caller reuses the peptide structure
        '      and thus we will get the values from the ***previous***
        '      parsed peptide if we don't do it.....
        '
        '      Note: this resetting is also done in ParseOneProteinHitTable().
        If True Then
            resetModFields(aPeptHitStru.modHits2)
            resetOtherFields(aPeptHitStru)
        End If

        'Changed PM_N15_BEFORE_PLUS 2007-08-08. Note: not used
        '  anyway, at least not for now.
        Dim extraMods As Boolean = False
        Dim modIndex2 As Integer = -1
        If False Then 'False: even if we are able to 
            '  handle the missing "+" we are still missing the
            '  modification count, the length of the
            '  peptide in case of N15 labeling. Instead we
            '  rely on an updated version of the N15 script...
            '
            'E.g. Mascot 2.2 and N15. Sample:
            '
            '  ASDASD.K,123-136 [heavy] + Deamidated (NQ)
            '
            'Note: there may be no "+", e.g.:
            '
            '  ASDASD.K,123-136 [heavy]

            'Note: this could also match some variable
            '      modifications after the "+" but that is OK.
            modIndex2 = seqPlusMods.IndexOf("[")
            If modIndex2 >= 0 Then
                'modIndex2 =  'Adjust index? Perhaps only if multiple character string.
                extraMods = True
            End If
        End If

        Dim modIndex As Integer = seqPlusMods.IndexOf("+")
        Dim plusMods As Boolean = modIndex >= 0

        If (plusMods Or extraMods) And aUseMod Then

            If extraMods Then
                modIndex = modIndex2
            End If

            'Changed PM_MOD_STATS 2006-08-15
            'This will, unfortunately create more temporary strings...
            Dim modStr As String = seqPlusMods.Substring(modIndex + 1)
            If True Then

                Dim oldCount As Integer = 0
                If mRawModStats2.ContainsKey(modStr) Then
                    oldCount = mRawModStats2(modStr)
                Else
                    Dim peter7 As Integer = 7 'One not seen before...
                End If
                Dim newCount As Integer = oldCount + 1
                mRawModStats2(modStr) = newCount
            End If

            'Changed PM_MEMORY_ALLOCATION 2004-08-01
            'Note: tags should already have been removed by removeHTMLtags().
            Trace.Assert(seqPlusMods.IndexOf(" ") < 0, _
              "PIL ASSERT. Unexpected   in: " & seqPlusMods)

            aPeptHitStru.modHits2 = _
              New Generic.List(Of modificationCountStruct)

            'Capture the number before the modification string if
            'there is any.
            If True Then
                Dim pepStr As String = aPeptHitStru.AASequence 'An alias - should
                '  not affect memory (?).

                Dim recognisedAModification As Boolean = False

                Dim quantitationModesObject As QuantitationModes_moreGeneral = _
                  mApplication.getQuantModes()

                'Changed PM_TYPESAFE 2007-08-02
                'Dim quantModificationsList As ArrayList = _
                '  quantitationModesObject.getModifications()
                Dim quantModificationsList2 As _
                  Generic.List(Of quantModificationStructure) = _
                    quantitationModesObject.getModifications()

                Dim modItem As quantModificationStructure
                For Each modItem In quantModificationsList2

                    Dim modCount As Integer = 0
                    MascotResultParser.modificationParseMatch( _
                      seqPlusMods, _
                      modItem.INTERNAL_matchStringForMod, modCount)

                    If modCount > 0 Then
                        recognisedAModification = True

                        'Changed PM_MODIFICATION_SANITYCHECK 2007-07-31
                        'Good place to check if the matched modification
                        'definition's amino acid set is consistent with
                        'the peptide sequence. E.g. if the line
                        'from Mascot is
                        '"R.STPSHGSVSSLNSTGSLSPK.H + Phospho (ST)" and a
                        'modification with AA set equal to "Y" matches
                        'with "Phospho" (no "Y" in peptide sequence).
                        If True Then
                            'An alias - should not affect memory (?).
                            Dim collapsedAA As String = _
                              modItem.INTERNAL_collapsedAAset

                            Dim defAAInPeptideSequence As Boolean = False

                            Dim lastIndex2 As Integer = collapsedAA.Length() - 1
                            Dim k As Integer
                            For k = 0 To lastIndex2
                                Dim colAA As String = collapsedAA(k)

                                Dim idx As Integer = pepStr.IndexOf(colAA, 0)
                                If idx >= 0 Then
                                    defAAInPeptideSequence = True
                                    Exit For 'No need to continue. We are
                                    '  looking for the case where there
                                    '  are ***no*** amino acids from the
                                    '  modification in the peptide sequence.
                                End If
                            Next k

                            If Not defAAInPeptideSequence Then
                                Dim msgStr As String = _
                                  "The peptide sequence, " & pepStr & _
                                  ", does not contain any of the amino acids " & _
                                  "of the matched modification, " & _
                                  modItem.modificationName & ": " & _
                                  collapsedAA & "."

                                Me.addParseError(msgStr)
                            Else
                                Dim peter2 As Integer = 2 'Sanity check OK.
                            End If
                        End If 'Modification sanity check.

                        'Add in the appropriate place in the peptides list of 
                        'modifications.
                        '
                        'Why is it named "update"?
                        Me.updateCountForModification( _
                          aPeptHitStru.modHits2, _
                          modItem.quantModificationID, modCount)

                        'Changed PM_MOD_STATS 2006-08-15
                        If True Then
                            Dim oldCount As Integer = 0
                            Dim key As Integer = modItem.quantModificationID
                            If mRecognisedModStats2.ContainsKey(key) Then
                                oldCount = mRecognisedModStats2(key)
                            Else
                                Dim peter7 As Integer = 7 'One not seen before...
                            End If
                            Dim newCount As Integer = oldCount + 1
                            mRecognisedModStats2(key) = newCount
                        End If

                        'Should we end the loop here? -effectively only matching
                        'for the first modification definition?
                    End If
                Next 'Through list of defined modifications (from a settings file).

                If recognisedAModification Then
                    Dim peter7 As Integer = 7
                Else
                    'Changed PM_MOD_STATS 2006-08-15
                    If True Then
                        Dim oldCount As Integer = 0
                        If mNoRecognisedModStats2.ContainsKey(modStr) Then
                            oldCount = mNoRecognisedModStats2(modStr)
                        Else
                            Dim peter7 As Integer = 7 'One not seen before...
                        End If
                        Dim newCount As Integer = oldCount + 1
                        mNoRecognisedModStats2(modStr) = newCount
                    End If
                End If
            End If
        Else
            'Changed PM_STRING_CLEANUP 2004-12-14
            'aPeptHitStru.AASequencePlusMods = ""
            aPeptHitStru.AASequencePlusMods = Nothing
        End If

        'Changed PM_MS3INTEGRATION 2004-06-02
        aPeptHitStru.MascotScorePlusMS3Score = aPeptHitStru.MascotScore
    End Sub 'ParsePeptMatch


    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    'This function is a candidate for a member function of a class 
    'representing a PeptideHitStructure.
    'Public Function formatMods(ByVal aPeptHit As PeptideHitStructure) As String
    Public Shared Function formatMods( _
      ByRef anInPeptHit As PeptideHitStructure, _
      ByRef aQuantitationModes As QuantitationModes_moreGeneral) _
      As String

        'Changed PM_MEMORY_EFFICIENCY 2007-03-22
        'Dim toReturn As String = ""
        Dim toReturnSB As StringBuilder = New StringBuilder(30)

        If Not anInPeptHit.modHits2 Is Nothing Then
            Dim len As Integer = anInPeptHit.modHits2.Count
            Dim lastIndex As Integer = len - 1
            Dim j As Integer

            'First see if we already have the modification in the peptide's list
            Dim prefix As String = ""
            For j = 0 To lastIndex
                Dim curItem As modificationCountStruct = _
                  anInPeptHit.modHits2(j)
                Dim modInfo As quantModificationStructure = _
                  aQuantitationModes.getModification(curItem.quantModificationID)

                'Changed PM_MEMORY_EFFICIENCY 2007-03-22
                'toReturn &= prefix & curItem.count.ToString & modInfo.formattedString
                toReturnSB.Append(prefix)
                toReturnSB.Append(curItem.count3)
                toReturnSB.Append(modInfo.formattedString)

                If prefix.Length = 0 Then
                    prefix = " "
                End If
            Next j
        End If

        'Changed PM_MEMORY_EFFICIENCY 2007-03-22
        'Return toReturn
        Return toReturnSB.ToString()
    End Function 'formatMods()


    '****************************************************************************
    '*    <placeholder for header>                                              *
    '*    This function is here because Structure OptionsStruct2                *
    '*    is defined in this file, but should it be somewhere else?             *
    '****************************************************************************
    Public Shared Function optionsStruct_To_optionsStruct2( _
      ByVal aOldVers As OptionsStruct) As OptionsStruct2

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

        'Changed PM_OBSOLETE_OR_DEADCODE_NOTE 2007-08-29
        'Note: this function has not been updated for all the new fields.
        '      Do we still need this function? With the new XML format we
        '      have forced a new file to be used, discarding the old one.

        Dim toReturn As OptionsStruct2

        toReturn.scoreA = aOldVers.scoreA
        toReturn.scoreB = aOldVers.scoreB
        toReturn.scoreC = aOldVers.scoreC
        toReturn.dontShowIPI = aOldVers.dontShowIPI
        toReturn.dontShowMosquito = aOldVers.dontShowMosquito
        toReturn.dontShowProtWithNoPeptInABC = aOldVers.dontShowProtWithNoPeptInABC
        toReturn.inclBoldRedPepts = aOldVers.inclBoldRedPepts
        toReturn.inclLightRedPepts = aOldVers.inclLightRedPepts
        toReturn.inclRedPeptsIfCheckedOnly = aOldVers.inclRedPeptsIfCheckedOnly
        toReturn.inclBoldBlackPeptsIfChecked = aOldVers.inclBoldBlackPeptsIfChecked
        toReturn.inclBoldBlackPepts = aOldVers.inclBoldBlackPepts
        toReturn.inclPeptsInParens = aOldVers.inclPeptsInParens
        toReturn.protDefaultValidationScoreThr = aOldVers.protDefaultValidation

        'Changed PM_VALIDATION_AS_PEPTFILTER 2007-09-05
        'toReturn.peptDefaultValidationScoreThr = aOldVers.peptDefaultValidation

        'Changed PM_GENERALISED_QUANT_MODE 2003-12-08
        'toReturn.quantMode = aOldVers.quantMode
        'Perhaps later: select some quant code, e.g. from the first in the list.

        toReturn.checkSum = aOldVers.checkSum
        toReturn.rawFileMode = rawFileModeEnum.enumAnalyst 'Default

        'Changed PM_PEPTIDEFILTER_GENERALISED 2007-08-24
        ''Changed PM_VS2005 2006-06-15
        ''Why can't these be in a block?????
        'toReturn.peptideFilterSpecification = Nothing 'Keep compiler happy.
        'toReturn.peptideModificationFilter2 = Nothing 'Keep compiler happy.
        toReturn.peptideFilters = Nothing

        toReturn.MStypes = QuantMSTypesEnum.enumAllMStypes

        'Changed PM_VALIDATION_AS_PEPTFILTER 2007-09-05
        'toReturn.peptideMaximumRelativeError_PPM = -9.0E+18
        'toReturn.peptideMinimumDeltaScore = -9.0E+18

        toReturn.quantModeCode = -1

        Return toReturn 'Compiler warnings (see below), but we are not really
        '  using this function anymore. It should be eliminated.
        '
        ' Variable 'toReturn' is used before it has been 
        ' assigned a value. A null reference exception could result at 
        ' runtime. Make sure the structure or all the reference 
        ' members are initialized before use	
    End Function 'optionsStruct_To_optionsStruct2


    'Changed PM_SEVERALWIFFS 2003-08-26
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Public Sub GetRawFiles(ByRef anOutRawFiles() _
      As massSpectrometryBase.fileSpecStructure)

        anOutRawFiles = mRawFiles
    End Sub 'GetRawFiles


    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Public Function getCorrelationReport() As String

        'Changed PM_CORR_CONTINUE_AND_REPORT 2004-02-11

        'Changed PM_SUPERFLUOUS_CODE 2006-10-26
        'mRetentionTimeCorrelator.correlationResult()

        Return mRetentionTimeCorrelator.getCorrelationReport()
    End Function 'getCorrelationReport


    'This function is completely general and should be moved somewhere else
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '*   Purpose: split a string in two, but with no string copying - just      *
    '*            an indication of the 2 resulting string; by start             *
    '*            index and length.                                             *
    '*                                                                          *
    '****************************************************************************
    Private Shared Sub split2( _
      ByRef anInStr As String, ByRef anInMatchStr As String, _
      ByRef anOutStartIndex1 As Integer, ByRef anOutLength1 As Integer, _
      ByRef anOutStartIndex2 As Integer, ByRef anOutLength2 As Integer, _
      Optional ByVal anInAllowMoreThanTwoParts As Boolean = False)

        'Later: eliminate the part that is the match string from the
        '       second part - different  anOutStartIndex2 and anOutLength2.

        If True Then 'For debugging
            Dim len As Integer = anInStr.Length
            If len > 0 Then
                Dim peter0 As Integer = 0
            End If
            If len > 3000 Then
                Dim peter30 As Integer = 30
            End If
            If len > 10000 Then
                Dim peter100 As Integer = 100
            End If
        End If

        Dim matchIndex As Integer = anInStr.IndexOf(anInMatchStr)
        Dim foundMatchingSameSection As Boolean = False
        If matchIndex >= 0 Then
            'At least 2 parts..

            Dim matchIndex2 As Integer = _
              anInStr.IndexOf(anInMatchStr, matchIndex + 1)

            anOutStartIndex2 = matchIndex
            anOutLength2 = anInStr.Length - anOutStartIndex2

            If Not anInAllowMoreThanTwoParts Then
                Trace.Assert(matchIndex2 < 0, _
                  "PIL ASSERT. The number of sections with '" & anInMatchStr & "' is greater than 1. Input string: " & _
                    ControlChars.NewLine & ControlChars.NewLine & anInStr)
            Else
                If matchIndex2 >= 0 Then
                    'There are 3 parts of more.
                    anOutLength2 = matchIndex2 - anOutStartIndex2

                End If
            End If
        Else
            'Not found, use the whole string
            matchIndex = anInStr.Length
            foundMatchingSameSection = True

            anOutStartIndex2 = anInStr.Length
            anOutLength2 = 0
        End If

        anOutStartIndex1 = 0 'By definition...
        anOutLength1 = matchIndex
    End Sub 'split2


    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Public Sub getParseErrorInfo( _
      ByRef anOutErrors As Integer, ByRef anOutErrorStr As String)

        anOutErrors = mChunkedParsingInfo.numToolTipParseErrors2
        anOutErrorStr = mChunkedParsingInfo.toolTipErrMsg2
    End Sub 'getParseErrorInfo


    'Changed PM_REFACTOR 2004-12-13
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Private Sub addParseError(ByRef anInErrorMsg As String)

        If mChunkedParsingInfo.toolTipErrMsg2 Is Nothing Then
            mChunkedParsingInfo.toolTipErrMsg2 = ""
        End If

        mChunkedParsingInfo.numToolTipParseErrors2 += 1 'Always count the total
        '  number of errors, but report only the first few.

        'Accept only the first 30 errors....
        If mChunkedParsingInfo.numToolTipParseErrors2 < 30 Then
            'Perhaps later: use StringBuilder.
            mChunkedParsingInfo.toolTipErrMsg2 &= anInErrorMsg
        Else
            Dim peter30 As Integer = 30
        End If
    End Sub 'addParseError


End Class 'MascotResultParser



    

    

Generated by script codePublish.pl at 2008-09-23T11:59:18.