Source code for MSQuant: signal.vb, MSQuant/msquant/src/main/massbase/signal.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: XYZ.                                                            * 
'*                                                                          *
'****************************************************************************

'****************************************************************************
'*                               CEBI                                       *
'*                    Software Development Group                            *
'*                         Peter Mortensen                                  *
'*                E-mail: NUKESPAMMERSdrmortensen@get2netZZZZZZ.dk          *
'*                 WWW: http://www.cebi.sdu.dk/                             *
'*                                                                          *
'*  Program for post-processing of result from search in mass               *
'*    spectrometric data.                                                   *
'*                                                                          *
'*    FILENAME:   signal.vb                                                 *
'*    MAIN_CLASS:   signal                                                  *
'*    STRUCTS_AND_CLASSES:   <none>                                         *
'*    TYPE:       VISUAL_BASIC                                              *
'*                                                                          *
'* CREATED: PM 2003-03-04   Vrs 1.0.                                        *
'* UPDATED: PM 2003-xx-xx                                                   *
'*                                                                          *
'****************************************************************************

'Future: 
' 1. There is so much to look forward to....
' 2.
' 3.
' 4.

Option Strict On
Option Explicit On 

Imports System.Text  'For StringBuilder

Imports System.Collections.Generic


'Changed PM_SUPERCHARGE 2003-11-03
'Imports Mascot_Parser.massSpectrometryBase 'For signalStructure
'Imports Mascot_Parser.SDUPutility
Imports massSpectrometryBase 'For signalStructure
Imports SDUPutility


'Why is "Public" needed in order to use it
'  in AnalystRawDataFileHandling.vb/returnDataPoints(); last parameter??
Public Module signalModule

    'Purpose, 2003-03-30: part of refactoring to make xxxx also work
    '  for MS spectra (TOF), not just for LC level signal (LC peak detection).
    'It is also part of the effort to separate GUI from non-GUI part of the application.
    '
    'Possible future:
    '  1. It could hold the signal state (protect direct access to signals)
    '  2. It could hide how to get to raw signals in an MS or MSMS
    '     spectrum. Hide details of: platform, spectrum type, manufacturer specifics, ...
    '  3.
    '  4.

    'Partly redundant information in SpecQuantStructure, but repeated
    'to avoid messing with the existing code.
    Public Structure ZZZsignalStructure
        Dim Xsig As Double
        Dim Ysig As Double 'Something representing signal intensity.
        '  It is unspecified: it can be the original signal or some
        '  derived quantitity: maximum signal strength, area (XIC),
        '  sum of signal strengths in a window, etc.
        Dim tagValue As Double 'Some value carried with each point. For
        '  instance: neutral centroid mass for each signal in a LC signal.
    End Structure 'ZZZsignalStructure


    'Changed PM_REFACTOR 2004-06-22. Moved from rawDataFileHandling.vb
    '****************************************************************************
    'd$ <summary>
    'd$   Purpose: 
    'd$     Organises values specifying max/min values for a range of datapoints.
    'd$ </summary>
    Public Structure dataPointsInfoStructure2

        'X range:
        Dim minX2 As Double
        Dim maxX2 As Double

        'Dim minY As Double
        'Dim maxY As Double

        Dim maximumSignal As signalStructure
        Dim minimumSignal As signalStructure
    End Structure 'dataPointsInfoStructure2


    'Specialised data structure...
    Public Structure LCPeakInfoStructure
        Dim maxIntensity As Double
        Dim calibratedNeutralMass As Double 'May not be needed if we
        '  are just interested in the relative mass error (ppm).
        Dim absRelError_PPM As Double

        Dim peakToBackgroundRatio As Double

        'Later:
        '  1. some mass accuracy measure, e.g. mass accuracy for max signal or some
        '     average of the best (or all) points within peak.
        '  2. xyz

        Dim LCpeakTimeCentroid As Double
        Dim LCpeakWindowStart As Integer
        Dim LCpeakWindowEnd As Integer
        Dim LCMaxTime As Double
        Dim LCMaxIndex As Integer

        'Changed PM_LCPEAK_MSMSEVENT 2004-02-02
        Dim MSMSeventInPeak As Boolean
    End Structure 'LCPeakInfoStructure


    'Changed PM_MANNREDUCTION_LEVEL 2005-09-05
    'Currently only used in GUI, but could be used for packing the parameters
    'for spectrum reduction.
    Public Structure reductionParametersStructure
        Dim MannReductionLevel2 As Integer
        Dim smartPickingLevel2 As Integer

        'Changed PM_USERSET_MS3_MATCHING_TOLERANCE 2007-07-13
        Dim smartPickingMassWindow As Double
        Dim matchingMassTolerance As Double 'No longer only reduction
        '  parameters with this field.

    End Structure 'reductionParametersStructure


    'Changed PM_TYPESAFE 2006-11-01. Changed to generics...
    '****************************************************************************
    '*  SUBROUTINE NAME:   SortByRelError                                       *
    'd$ <summary> N/A. ...  
    'd$      Note: descending sort                    </summary>
    Public Class SortByRelError
        Implements System.Collections.Generic.IComparer(Of LCPeakInfoStructure)

        Public Function Compare( _
          ByVal aItem1 As LCPeakInfoStructure, _
          ByVal aItem2 As LCPeakInfoStructure) _
          As Integer _
          Implements _
            System.Collections.Generic.IComparer(Of LCPeakInfoStructure).Compare

            Dim toReturn As Integer = 0
            If aItem1.absRelError_PPM < aItem2.absRelError_PPM Then
                toReturn = 1
            Else
                If aItem1.absRelError_PPM > aItem2.absRelError_PPM Then
                    toReturn = -1
                Else
                    'Equal.... 
                    Dim peter9 As Integer = 9
                End If
            End If
            Return toReturn
        End Function 'Compare
    End Class 'SortByRelError


    'Changed PM_TYPESAFE 2006-11-01. Changed to generics...
    '****************************************************************************
    '*  SUBROUTINE NAME:   SortByX                                              *
    'd$ <summary> N/A. ...  
    'd$      Note: ascending sort                    </summary>
    Public Class SortByX
        'Implements IComparer(Of LCPeakInfoStructure)
        Implements System.Collections.Generic.IComparer(Of LCPeakInfoStructure)

        Public Function Compare( _
          ByVal aItem1 As LCPeakInfoStructure, _
          ByVal aItem2 As LCPeakInfoStructure) _
          As Integer _
          Implements _
            System.Collections.Generic.IComparer(Of LCPeakInfoStructure).Compare
            'Implements System.Collections.IComparer.Compare

            Dim toReturn As Integer = 0
            If aItem1.LCpeakTimeCentroid < aItem2.LCpeakTimeCentroid Then
                toReturn = -1
            Else
                If aItem1.LCpeakTimeCentroid > aItem2.LCpeakTimeCentroid Then
                    toReturn = 1
                Else
                    'Equal.... 
                    Dim peter9 As Integer = 9
                End If
            End If
            Return toReturn
        End Function 'Compare
    End Class 'SortByX


    'Changed PM_DTASC_MEMORY 2004-10-15
    'This class exists to reduce the information required to pass in the parameters
    'for the recursive function internal_findThePeaks(). It is used for a sort of
    'read-on-demand; the information in this class seldomly used (but is needed) and
    'is either read-only or global to the purpose of the function.
    Public Class peaksInfoStorage

        Dim mMaxY As Double


        'Changed PM_REFACTOR 2006-10-12
        'Dim mSignal As ArrayList
        Dim mSignal As Generic.List(Of massSpectrometryBase.signalStructure)

        Dim mInAASequence As String
        Dim mCalibratedMeasuredMZ As Double
        Dim mCharge As Integer
        Dim mDumpString As StringBuilder
        Dim mMaximumXDistanceForPeakDetection As Double
        Dim mMaximumXDistanceForMinima As Double

        Dim mMascotCalculatedMW As Double
        Dim mMSMSretentionTimeMinutes As Double
        Dim mConsiderMSMSevent As Boolean

        'Changed PM_TYPESAFE 2006-11-01
        'Dim mPeakCandidates As ArrayList
        Dim mPeakCandidates As Generic.List(Of LCPeakInfoStructure)


        Dim mConsiderSet As Boolean 'For error checking

        Dim mFindPeaksMaxSearchLevel As Integer
        Dim mActualDeepestSearchLevel As Integer


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub New()
            mConsiderSet = False

            mDumpString = New StringBuilder

            'Changed PM_TYPESAFE 2006-11-01. Lazy instantiate it.
            'mPeakCandidates = New ArrayList

            mMaxY = -1000000000.0
            mSignal = Nothing
            mInAASequence = ""
            mCalibratedMeasuredMZ = -300.0
            mCharge = -2
            mMaximumXDistanceForPeakDetection = -300.0

            mMaximumXDistanceForMinima = -300.0

            mMascotCalculatedMW = -300.0
            mMSMSretentionTimeMinutes = -300.0

            mActualDeepestSearchLevel = -2
            mFindPeaksMaxSearchLevel = -2
        End Sub


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub addToDumpString(ByRef aStringToAdd As String)
            mDumpString.Append(aStringToAdd)
        End Sub


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getDumpString() As String
            'Trace.Assert(mDumpString.Length > 0, "PIL ASSERT. Dump string not set....")
            Return mDumpString.ToString
        End Function 'getDumpString


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub addToPeakCandidates(ByRef aInPeakCandidate As LCPeakInfoStructure)

            'Changed PM_TYPESAFE_ANDLAZYINSTANTIATE 2006-11-01
            'Lazy instantiate.
            If mPeakCandidates Is Nothing Then
                mPeakCandidates = New Generic.List(Of LCPeakInfoStructure)
            End If

            mPeakCandidates.Add(aInPeakCandidate)
        End Sub 'addToPeakCandidates


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getPeakCandidates() _
        As Generic.List(Of LCPeakInfoStructure)
            'Old:
            '  Return type
            '    As ArrayList

            Return mPeakCandidates 'Note: can be empty...
        End Function 'getPeakCandidates


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub setMaxY(ByVal aMaxY As Double)
            mMaxY = aMaxY
        End Sub 'setMaxY


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getMaxY() As Double
            Trace.Assert(mMaxY > -290.0, "PIL ASSERT. <message>.")
            Return mMaxY
        End Function 'getMaxY


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub setSignal( _
          ByRef anInSignal As Generic.List(Of massSpectrometryBase.signalStructure))

            'Old:
            '  ByRef anInSignal As ArrayList


            mSignal = anInSignal 'Will this make a copy?? Hopefully not
        End Sub 'setSignal


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getSignal() _
        As Generic.List(Of massSpectrometryBase.signalStructure)

            'Old return type:
            '  ArrayList


            Trace.Assert(Not mSignal Is Nothing, "PIL ASSERT. <message>.")

            Return mSignal
        End Function 'getSignal


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub setAASequence(ByRef anInAASequence As String)
            mInAASequence = anInAASequence
        End Sub 'setAASequence


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getAASequence() As String
            Trace.Assert(mInAASequence <> "", "PIL ASSERT. <message>.")
            Return mInAASequence
        End Function 'getAASequence


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub setCalibratedMeasuredMZ(ByVal anCalibratedMeasuredMZ As Double)
            mCalibratedMeasuredMZ = anCalibratedMeasuredMZ
        End Sub


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getCalibratedMeasuredMZ() As Double
            Trace.Assert(mCalibratedMeasuredMZ > -290.0, "PIL ASSERT. <message>.")
            Return mCalibratedMeasuredMZ
        End Function


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub setCharge(ByVal aCharge As Integer)
            mCharge = aCharge
        End Sub


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getCharge() As Integer
            Trace.Assert(mCharge >= -1, "PIL ASSERT. <message>.")
            Return mCharge
        End Function


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub setMaximumXDistanceForPeakDetection( _
          ByVal anMaximumXDistanceForPeakDetection As Double)
            mMaximumXDistanceForPeakDetection = anMaximumXDistanceForPeakDetection
        End Sub


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub setMaximumXDistanceForMinima( _
          ByVal anMaximumXDistanceForMinima As Double)
            mMaximumXDistanceForMinima = anMaximumXDistanceForMinima
        End Sub


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getMaximumXDistanceForPeakDetection() As Double
            Trace.Assert(mMaximumXDistanceForPeakDetection > -290.0, "PIL ASSERT. <message>.")
            Return mMaximumXDistanceForPeakDetection
        End Function


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getMaximumXDistanceForMinima() As Double
            Trace.Assert(mMaximumXDistanceForMinima > -290.0, "PIL ASSERT. <message>.")
            Return mMaximumXDistanceForMinima
        End Function


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub setMascotCalculatedMW(ByVal anMascotCalculatedMW As Double)
            mMascotCalculatedMW = anMascotCalculatedMW
        End Sub


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getMascotCalculatedMW() As Double
            Trace.Assert(mMascotCalculatedMW > -290.0, "PIL ASSERT. <message>.")
            Return mMascotCalculatedMW
        End Function


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub setMSMSretentionTimeMinutes(ByVal aMSMSretentionTimeMinutes As Double)
            mMSMSretentionTimeMinutes = aMSMSretentionTimeMinutes
        End Sub


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getMSMSretentionTimeMinutes() As Double
            Trace.Assert(mMSMSretentionTimeMinutes > -290.0, "PIL ASSERT. <message>.")
            Return mMSMSretentionTimeMinutes
        End Function


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub setConsiderMSMSevent(ByVal aConsiderMSMSevent As Boolean)
            mConsiderSet = True
            mConsiderMSMSevent = aConsiderMSMSevent
        End Sub


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getConsiderMSMSevent() As Boolean
            Trace.Assert(mConsiderSet = True, "PIL ASSERT. <message>.")
            Return mConsiderMSMSevent
        End Function


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub setFindPeaksMaxSearchLevel(ByVal aFindPeaksMaxSearchLevel As Integer)
            mFindPeaksMaxSearchLevel = aFindPeaksMaxSearchLevel
        End Sub


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getFindPeaksMaxSearchLevel() As Integer
            Trace.Assert(mFindPeaksMaxSearchLevel >= 0, "PIL ASSERT. <message>.")
            Return mFindPeaksMaxSearchLevel
        End Function


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub setActualDeepestSearchLevel(ByVal aActualDeepestSearchLevel As Integer)
            mActualDeepestSearchLevel = aActualDeepestSearchLevel
        End Sub


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getActualDeepestSearchLevel() As Integer
            Trace.Assert(mActualDeepestSearchLevel >= 0, "PIL ASSERT. <message>.")
            Return mActualDeepestSearchLevel
        End Function

    End Class 'peaksInfoStorage


    'Opearations on signals (e.g. LC or MS level), not necesseraly uniformly sampled.
    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Public Class BSignal

        'Changed PM_REFACTOR_FINDPEAK_ 2003-03-30. Moved from QuantWindow.vb.
        'Changed PM_LC_PEAKDETECTION 2003-03-20
        'Type of aSignal: signalStructure
        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Shared Sub findSignalPeak( _
          ByRef aSignal As Generic.List(Of massSpectrometryBase.signalStructure), _
          ByVal anStartIndex As Integer, ByVal anEndIndex As Integer, _
          ByVal aMaximumXDistanceForPeakDetection As Double, _
          ByVal aMaximumXDistanceForMinima As Double, _
          ByRef anOutSignalPeakXCentroid As Double, _
            ByRef anOutSignalPeakYCentroid As Double, _
          ByRef anOutSignalPeakIndexStart As Integer, _
            ByRef anOutSignalPeakIndexEnd As Integer, _
          ByRef anOutSignalPeakWindowStart As Integer, _
            ByRef anOutSignalPeakWindowEnd As Integer, _
          ByRef anOutSignalMaxX As Double, ByRef anOutSignalMaxY As Double, _
          ByRef anOutSignalMaxIndex As Integer, _
          ByRef anOutBackgroundLevel As Double _
          )

            'Old:
            '  ByRef aSignal As ArrayList


            Dim stoppedByMaxDist_left As Boolean = False
            Dim stoppedByMaxDist_right As Boolean = False

            If anEndIndex = 81 AndAlso anStartIndex = 0 Then
                Dim peter81 As Integer = 81
            End If

            'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-18.
            Const IDENTICALZERO_THRESHOLD As Double = 0.0011

            'Changed PM_REFACTOR_FINNEGAN 2003-07-25
            'We can not currently handle empty signals....
            Dim sLen As Integer = aSignal.Count
            Trace.Assert(sLen > 0, "PIL ASSERT. Empty signal. In findSignalPeak().")

            Dim firstX As Double = aSignal(0).Xsig

            Dim lastIndex As Integer = sLen - 1
            Trace.Assert(sLen > 0, _
              "PIL ASSERT: unexpected empty list in findSignalPeak()")

            Trace.Assert(anEndIndex >= anStartIndex, _
              "PIL ASSERT: anEndIndex >= anStartIndex in findSignalPeak()")
            Trace.Assert(anStartIndex >= 0, _
              "PIL ASSERT: anStartIndex >= 0 in findSignalPeak()")

            'This would also be caught by the run time, but we want to
            'put a (hopefully) more understandable message to the user...
            Dim endX As Double = _
              aSignal(lastIndex).Xsig / 60.0 'LC/minutes dependence...
            Trace.Assert(anEndIndex < sLen, _
              "PIL ASSERT. Could not find signal peak. The end signal x was specified outside the end of range (" & _
              endX & "). Report to a developer near you.")

            Dim somePoint As signalStructure

            Dim minYpoint As signalStructure
            minYpoint.Ysig = 1.0E+20

            Dim maxYpoint As signalStructure
            maxYpoint.Ysig = -1.0E+20

            Dim minYindex As Integer
            Dim maxYindex As Integer
            Dim index As Integer = 0
            Dim maxYtime As Double = -1.0E+20
            For Each somePoint In aSignal
                'Trace.Assert(somePoint.Ysig > 0.00001, _
                '  "PIL ASSERT. Bad Y value: (" & _
                '  somePoint.Ysig & "). Report to a developer near you.")

                If index >= anStartIndex And index <= anEndIndex Then
                    If somePoint.Ysig < minYpoint.Ysig Then
                        minYpoint = somePoint
                        minYindex = index
                    End If
                    If somePoint.Ysig > maxYpoint.Ysig Then
                        maxYpoint = somePoint
                        maxYindex = index
                        maxYtime = somePoint.Xsig
                    End If
                    'index += 1 'Why was it here????

                End If
                index += 1
            Next
            Dim minY As Double = minYpoint.Ysig
            Dim maxY As Double = maxYpoint.Ysig

            anOutSignalMaxX = maxYtime
            anOutSignalMaxY = maxY
            anOutSignalMaxIndex = maxYindex

            Dim ySize As Double = maxY - minY
            Dim yThres As Double = ySize * 0.3 'Hardcoded 30 % limit...
            Dim yThresAbsU As Double = yThres + minY

            'To find the peak we do a LaserOne style inside-out peak detection....

            'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-21
            'Dim xStartIndexForCentroid As Integer = maxYindex
            'Dim xEndIndexForCentroid As Integer = maxYindex
            Dim xStartIndexForCentroid As Integer = maxYindex - 1
            Dim xEndIndexForCentroid As Integer = maxYindex + 1

            'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-21
            Dim pointsUsed As Integer = 1  'One because we have already the max point...

            'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-18. Condition added...

            'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-21
            'Dim peakLeftSideY As Double = -1.0
            Dim peakLeftSideY As Double = maxY

            'Note: condition relies on boolean shortcircuit...
            Dim done_Left As Boolean = False
            While Not done_Left
                If xStartIndexForCentroid >= anStartIndex Then
                    Dim curPoint As signalStructure = aSignal(xStartIndexForCentroid)
                    Dim curY As Double = curPoint.Ysig
                    Dim curX As Double = curPoint.Xsig

                    'Changed PM_PEAKFIND_MAXFINDDISTANCE 2004-06-25
                    Dim xDist As Double = maxYtime - curX 'We don't need Abs(), we
                    '  are sure of the sign...

                    'Changed PM_SMARTPICKING_FIX 2004-10-27
                    'Check this first, never look at points too far during
                    'peak detection.
                    If xDist <= aMaximumXDistanceForPeakDetection Then
                        If curY >= yThresAbsU Or _
                           curY <= IDENTICALZERO_THRESHOLD Then

                            'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-18
                            'Dim curY As Double = DirectCast(aSignal(xStartIndexForCentroid), _
                            '  signalStructure).Ysig
                            If curY > IDENTICALZERO_THRESHOLD Then
                                peakLeftSideY = curY

                                'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-21
                                pointsUsed += 1
                            End If
                            xStartIndexForCentroid -= 1
                        Else
                            done_Left = True
                        End If
                    Else
                        done_Left = True
                    End If
                Else
                    done_Left = True
                    stoppedByMaxDist_left = True
                End If
            End While
            xStartIndexForCentroid += 1

            'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-18. Condition added...
            'Note: condition relies on boolean shortcircuit...

            'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-23
            'Dim peakRightSideY As Double = -1.0
            Dim peakRightSideY As Double = maxY

            Dim done_Right As Boolean = False
            While Not done_Right
                If xEndIndexForCentroid <= anEndIndex Then
                    Dim curPoint As signalStructure = _
                      aSignal(xEndIndexForCentroid)
                    Dim curY As Double = curPoint.Ysig
                    Dim curX As Double = curPoint.Xsig

                    'Changed PM_PEAKFIND_MAXFINDDISTANCE 2004-06-25
                    Dim xDist As Double = curX - maxYtime 'We don't need Abs(), we
                    '  are sure of the sign...

                    'Changed PM_SMARTPICKING_FIX 2004-10-27
                    'Check this first, never look at points too far during
                    'peak detection.
                    If xDist <= aMaximumXDistanceForPeakDetection Then
                        If curY >= yThresAbsU Or _
                           curY <= IDENTICALZERO_THRESHOLD Then

                            'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-18
                            'Dim curY As Double = DirectCast(aSignal(xEndIndexForCentroid), _
                            '  signalStructure).Ysig
                            If curY > IDENTICALZERO_THRESHOLD Then
                                peakRightSideY = curY

                                'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-21
                                pointsUsed += 1
                            End If
                            xEndIndexForCentroid += 1
                        Else
                            done_Right = True
                        End If
                    Else
                        done_Right = True
                    End If
                Else
                    done_Right = True
                    stoppedByMaxDist_right = True
                End If
            End While
            xEndIndexForCentroid -= 1

            Trace.Assert(xEndIndexForCentroid >= xStartIndexForCentroid, _
              "PIL ASSERT: xEndIndexForCentroid>=xStartIndexForCentroid. xEndIndexForCentroid: " & _
              xEndIndexForCentroid & ". xEndIndexForCentroid: " & xEndIndexForCentroid)

            'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-21
            'Dim pointsUsed As Integer = xEndIndexForCentroid - xStartIndexForCentroid + 1

            'Find the x og y centroid
            Dim weigthedRetSum As Double = 0.0
            Dim ySum As Double = 0.0
            Dim xWeightSum As Double = 0.0
            Dim yWeightSum As Double = 0.0
            Dim areaSum As Double = 0.0
            Dim prevPoint As signalStructure = aSignal(xStartIndexForCentroid)

            ' 'Changed PM_NONUNIFORMSAMPLING_LCCENTROID 2003-03-24
            ' 'Make sure we use the last point
            ' Dim indexEnd As Integer = xEndIndexForCentroid
            ' indexEnd += 1 'For using the last point, for forward approximation
            ' If indexEnd > anEndIndex Then
            '     indexEnd = anEndIndex
            ' End If

            If pointsUsed >= 2 Then
                Dim j As Integer
                For j = xStartIndexForCentroid To xEndIndexForCentroid
                    Dim curSignalPoint As signalStructure = aSignal(j)

                    'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-18. 
                    'Ignore points with identical zero as y-value.
                    If curSignalPoint.Ysig > IDENTICALZERO_THRESHOLD Then
                        'Old method that assumes constant x sampling:
                        ' Dim wCon As Double = curSignalPoint.Ysig * curSignalPoint.Xsig
                        ' weigthedRetSum += wCon
                        ' ySum += curSignalPoint.Ysig

                        'Forward approximation
                        ' 'Changed PM_NONUNIFORMSAMPLING_LCCENTROID 2003-03-24
                        ' 'Left point is defined as determining y value (including area).
                        ' Dim area As Double = _
                        '   (curSignalPoint.Xsig - prevPoint.Xsig) * prevPoint.Ysig
                        ' Dim x As Double = (prevPoint.Xsig + curSignalPoint.Xsig) / 2
                        ' Dim y As Double = 0.5 * prevPoint.Ysig
                        ' Dim xw As Double = x * area
                        ' Dim yw As Double = y * area
                        ' xWeightSum += xw
                        ' yWeightSum += yw
                        ' areaSum += area

                        'Bilinear approximation
                        Dim yMin As Double
                        Dim yMax As Double
                        Dim xFactor As Double
                        If prevPoint.Ysig < curSignalPoint.Ysig Then
                            yMin = prevPoint.Ysig
                            yMax = curSignalPoint.Ysig
                            xFactor = 2.0 / 3.0
                        Else
                            yMin = curSignalPoint.Ysig
                            yMax = prevPoint.Ysig
                            xFactor = 1.0 / 3.0
                        End If
                        Dim yDiff As Double = yMax - yMin
                        Dim xDiff As Double = curSignalPoint.Xsig - prevPoint.Xsig

                        'Rectangular area under the triangle.
                        Dim area1 As Double = xDiff * yMin
                        Dim x1 As Double = (prevPoint.Xsig + curSignalPoint.Xsig) / 2
                        Dim y1 As Double = 0.5 * yMin
                        Dim xw1 As Double = x1 * area1
                        Dim yw1 As Double = y1 * area1
                        xWeightSum += xw1
                        yWeightSum += yw1
                        areaSum += area1

                        'The triangle above the triangle.
                        Dim area2 As Double = 0.5 * xDiff * yDiff
                        Dim x2 As Double = xFactor * xDiff + prevPoint.Xsig
                        Dim y2 As Double = yDiff / 3 + yMin
                        Dim xw2 As Double = x2 * area2
                        Dim yw2 As Double = y2 * area2
                        xWeightSum += xw2
                        yWeightSum += yw2
                        areaSum += area2

                        prevPoint = curSignalPoint
                    End If
                Next j

                Trace.Assert(areaSum > 0.0, "PIL ASSERT. areaSum > 0.0. In findSignalPeak().")
                'Changed PM_NONUNIFORMSAMPLING_LCCENTROID 2003-03-24
                'anOutSignalPeakXCentroid = weigthedRetSum / ySum
                'anOutSignalPeakYCentroid = ySum / pointsUsed
                anOutSignalPeakXCentroid = xWeightSum / areaSum
                anOutSignalPeakYCentroid = yWeightSum / areaSum
            Else 'pointsUsed >= 2
                'Should mean a single point...
                Trace.Assert(pointsUsed = 1, "PIL ASSERT: pointsForCentroid = 1. In findSignalPeak()")
                Dim firstSignalPoint As signalStructure = _
                  aSignal(xStartIndexForCentroid)

                anOutSignalPeakXCentroid = firstSignalPoint.Xsig
                anOutSignalPeakYCentroid = firstSignalPoint.Ysig
            End If

            Trace.Assert(anOutSignalPeakXCentroid > -1000000.0 And _
              anOutSignalPeakXCentroid < 1000000.0, _
              "PIL ASSERT. anOutSignalPeakXCentroid out of range: " & _
              anOutSignalPeakXCentroid)

            'For FTMS we can get very high values. This value has been
            'seen: 2004785.7348632813
            Trace.Assert(anOutSignalPeakYCentroid > -1000000000.0 And _
              anOutSignalPeakYCentroid < 1000000000.0, _
              "PIL ASSERT. anOutSignalPeakYCentroid out of range: " & _
              anOutSignalPeakYCentroid)

            anOutSignalPeakIndexStart = xStartIndexForCentroid
            anOutSignalPeakIndexEnd = xEndIndexForCentroid

            'Changed PM_EXTENDED_LCPEAK_TIMEWINDOW 2003-03-24
            'Find local minima to the left and right of the
            'points used for the centroid.

            If True Then 'to the left...
                anOutSignalPeakWindowStart = anOutSignalPeakIndexStart

                'Dim prevY As Double = DirectCast( _
                '                aSignal(anOutSignalPeakWindowStart), _
                '                signalStructure).Ysig
                Dim prevY As Double = peakLeftSideY

                anOutSignalPeakWindowStart -= 1

                Dim stopNow As Boolean = False
                While Not stopNow And anOutSignalPeakWindowStart >= anStartIndex

                    Dim curPoint As signalStructure = _
                      aSignal(anOutSignalPeakWindowStart)
                    Dim curY As Double = curPoint.Ysig

                    'Changed PM_SMARTPICKING_FIX 2004-10-27
                    Dim curX As Double = curPoint.Xsig
                    Dim xDist As Double = maxYtime - curX 'We don't need Abs(), we
                    '  are sure of the sign...

                    'Changed PM_SMARTPICKING_FIX 2004-10-27
                    If xDist <= aMaximumXDistanceForMinima Then
                        'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-18
                        If curY > IDENTICALZERO_THRESHOLD Then
                            If curY <= prevY Then
                            Else
                                stopNow = True
                            End If
                            prevY = curY
                        End If
                    Else
                        stopNow = True
                        stoppedByMaxDist_left = True
                    End If
                    If Not stopNow Then
                        anOutSignalPeakWindowStart -= 1
                    End If
                End While
                anOutSignalPeakWindowStart += 1
                'If anOutSignalPeakWindowStart < anStartIndex Then
                'anOutSignalPeakWindowStart = anStartIndex
                'End If
            End If 'To the left

            'Those 2 blocks have a lot in common. Can we make it less redundant?
            If True Then 'to the right... 
                anOutSignalPeakWindowEnd = anOutSignalPeakIndexEnd

                'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-18
                'Dim prevY As Double = DirectCast( _
                '                aSignal(anOutSignalPeakWindowEnd), _
                '                signalStructure).Ysig
                Dim prevY As Double = peakRightSideY

                anOutSignalPeakWindowEnd += 1

                Dim stopNow As Boolean = False
                While Not stopNow And anOutSignalPeakWindowEnd <= anEndIndex
                    Dim curPoint As signalStructure = _
                      aSignal(anOutSignalPeakWindowEnd)
                    Dim curY As Double = curPoint.Ysig

                    'Changed PM_SMARTPICKING_FIX 2004-10-27
                    Dim curX As Double = curPoint.Xsig
                    Dim xDist As Double = curX - maxYtime 'We don't need Abs(), we
                    '  are sure of the sign...

                    'Changed PM_SMARTPICKING_FIX 2004-10-27
                    If xDist <= aMaximumXDistanceForMinima Then
                        'Changed PM_IGNORE_ZEROS_IN_LCPROFILE_ 2004-06-18
                        If curY > IDENTICALZERO_THRESHOLD Then
                            If curY <= prevY Then
                            Else
                                stopNow = True
                            End If
                            prevY = curY
                        End If
                    Else
                        stopNow = True
                        stoppedByMaxDist_right = True
                    End If

                    If Not stopNow Then
                        anOutSignalPeakWindowEnd += 1
                    End If
                End While
                anOutSignalPeakWindowEnd -= 1
            End If

            'Changed PM_BETTER_LCPEAK_DETECTION 2003-10-16
            '  as the background.
            Dim minYinPeakWindow As Double = 1000000000.0
            Dim k As Integer
            For k = anOutSignalPeakWindowStart To anOutSignalPeakWindowEnd
                Dim curY As Double = aSignal(k).Ysig

                'Changed PM_LCPEAKDETECT_IGNORE_ZERO_FOR_BACKGROUND 2003-10-21
                'If curY < minYinPeakWindow Then
                If curY > IDENTICALZERO_THRESHOLD AndAlso _
                   curY < minYinPeakWindow Then 'IDENTICALZERO_THRESHOLD: ignore
                    '  points zero value. This would give very high ..??
                    minYinPeakWindow = curY
                End If
            Next
            anOutBackgroundLevel = minYinPeakWindow 'For now: just use the minimum value

            Dim stoppedByMax_bothDirs As Boolean = _
              stoppedByMaxDist_left And stoppedByMaxDist_right
            If stoppedByMax_bothDirs Then
                Dim peter9 As Integer = 9
            End If

            Trace.Assert(anOutSignalPeakWindowStart <= anOutSignalPeakIndexStart, _
              "PIL ASSERT: anOutSignalPeakWindowStart <= anOutSignalPeakIndexStart in findSignalPeak()")
            Trace.Assert(anOutSignalPeakWindowEnd >= anOutSignalPeakIndexEnd, _
              "PIL ASSERT: anOutSignalPeakWindowEnd >= anOutSignalPeakIndexEnd in findSignalPeak()")

            'Avoid a single point defining an signal peak...
            Trace.Assert(anOutSignalPeakWindowStart < anOutSignalPeakWindowEnd Or _
              stoppedByMax_bothDirs, _
              "PIL ASSERT: single point signal peak - anOutSignalPeakWindowStart < anOutSignalPeakWindowEnd. In findSignalPeak()")
        End Sub 'findSignalPeak()


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Shared Sub dumpSignalToDisk(ByVal aHeadline As String, _
          ByRef anInSignal As Generic.List(Of massSpectrometryBase.signalStructure), _
          ByVal aFullPathFileName As String)

            Dim toOutputSB As StringBuilder = New StringBuilder(300) 'Instead 
            '  estimate on length of input signal?

            'Dim tableHeaders As String = _
            '  aHeadline & PILInputOutput.LINEEND & PILInputOutput.LINEEND & _
            '  "Index" & vbTab & "x" & vbTab & "y" & PILInputOutput.LINEEND
            toOutputSB.Append(aHeadline)
            toOutputSB.Append(PILInputOutput.LINEEND)
            toOutputSB.Append(PILInputOutput.LINEEND)
            toOutputSB.Append("Index")
            toOutputSB.Append(vbTab)
            toOutputSB.Append("x")
            toOutputSB.Append(vbTab)
            toOutputSB.Append("y")
            toOutputSB.Append(PILInputOutput.LINEEND)

            'Dim str As String = tableHeaders

            Dim index As Integer = 0
            Dim sPoint As signalStructure
            For Each sPoint In anInSignal

                'Str &= index & vbTab & _
                '  sPoint.Xsig & vbTab & sPoint.Ysig & PILInputOutput.LINEEND
                toOutputSB.Append(index)
                toOutputSB.Append(vbTab)
                toOutputSB.Append(sPoint.Xsig)
                toOutputSB.Append(vbTab)
                toOutputSB.Append(sPoint.Ysig)
                toOutputSB.Append(PILInputOutput.LINEEND)

                index += 1
            Next

            PILInputOutput.pushToFile(aFullPathFileName, toOutputSB.ToString)
        End Sub 'dumpSignalToDisk


        'Changed PM_REFACTOR 2004-06-22
        'Changed PM_LCPROFILE_DUMP 2003-11-16
        '****************************************************************************
        '*  SUBROUTINE NAME:   findLCProfileProperties                              *
        'd$ <summary>
        'd$   Purpose: Find some properties of the LC profile, e.g. max point, XYZ
        'd$     Type of elements in anInSignal: signalStructure
        'd$ 
        'd$   <see cref="T:VBXMLDoc.CVBXMLDoc" />.
        'd$ </summary>
        Public Shared Sub findSignalProfileProperties( _
          ByRef anInSignal As _
            Generic.List(Of massSpectrometryBase.signalStructure), _
          ByRef anOutSignalProfileDescriptor As dataPointsInfoStructure2)

            'Old:
            '  ByRef anInSignal As ArrayList


            Dim maxYsignal As Double = -1000000000.0
            Dim minYsignal As Double = 1000000000.0

            Dim lastIndex As Integer = anInSignal.Count - 1
            Dim minX As Double = anInSignal.Item(0).Xsig
            Dim maxX As Double = anInSignal.Item(lastIndex).Xsig

            Dim sPoint As signalStructure
            For Each sPoint In anInSignal
                Dim curY As Double = sPoint.Ysig
                If curY > maxYsignal Then
                    maxYsignal = curY
                    anOutSignalProfileDescriptor.maximumSignal = sPoint
                End If
                If curY < minYsignal Then
                    minYsignal = curY
                    anOutSignalProfileDescriptor.minimumSignal = sPoint
                End If
                'sIndex += 1
            Next

            anOutSignalProfileDescriptor.minX2 = minX
            anOutSignalProfileDescriptor.maxX2 = maxX
        End Sub 'findLCProfileProperties


        'Changed PM_DTASC_MEMORY 2004-10-15. Refactored out the private part of findThePeaks
        '  in order to avoid passing constant values in the recursive calls.
        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Private Shared Sub internal_findThePeaks( _
          ByRef anInfo As peaksInfoStorage, _
          ByVal anStartIndex As Integer, ByVal anEndIndex As Integer, _
          ByVal aSearchLevel As Integer, _
          ByRef anInOutDumpFileCounter As Integer _
          )

            Dim pointsToUse As Integer = anEndIndex - anStartIndex + 1

            'Changed PM_CENTROIDEDDATA_PEAKDETECTION 2005-01-21
            'Dim minimumNumberOfPoints As Integer = 1
            Dim minimumNumberOfPoints As Integer = 0

            Dim doFindPeakAtThisLevel As Boolean = True
            If pointsToUse <= minimumNumberOfPoints Then 'We don't accept LC ranges with only a single point.
                doFindPeakAtThisLevel = False
            Else
                Dim findPeaksMaxSearchLevel As Integer = _
                  anInfo.getFindPeaksMaxSearchLevel()
                If aSearchLevel > findPeaksMaxSearchLevel Then
                    doFindPeakAtThisLevel = False
                Else
                    Dim curDeepestSearchLevel As Integer = anInfo.getActualDeepestSearchLevel()
                    If aSearchLevel > curDeepestSearchLevel Then
                        anInfo.setActualDeepestSearchLevel(aSearchLevel)
                    Else
                        Dim peter9 As Integer = 9
                    End If
                End If
            End If

            If doFindPeakAtThisLevel Then 'We don't accept LC ranges with only a single point.

                Dim outLCpeakTimeCentroid As Double
                Dim outLCpeakIntensity As Double
                Dim outLCPeakIndexStart As Integer
                Dim outLCPeakIndexEnd As Integer
                Dim outLCpeakWindowStart As Integer
                Dim outLCpeakWindowEnd As Integer
                Dim outLCMaxTime As Double
                Dim outLCMaxIntensity As Double
                Dim LCMaxIndex As Integer
                Dim backGround As Double

                'Dim inSignal As ArrayList = anInfo.getSignal()
                Dim inSignal As _
                  Generic.List(Of massSpectrometryBase.signalStructure) = _
                    anInfo.getSignal()

                If False Then
                    'Test only, but should be out-factored - we may want to provide
                    'a menu command to dump the LC peak profiles.
                    Dim doDump As Boolean = False 'True Or mDumpFileCounter = 0
                    Dim maxY As Double = anInfo.getMaxY()
                    If maxY > 210000 Then 'Thats for
                        '  Finnegan FTMS, typical high intensity value.
                        doDump = True
                    Else
                        Dim peter21 As Integer = 21
                    End If

                    If aSearchLevel > 0 Then 'Only once...
                        doDump = False
                    Else
                        'Only needed for testing..
                        'Dim msMea As Double = mPept.calibratedMeasuredMass
                        'Dim msMascot As Double = mPept.MascotCalculatedMW
                        'Dim absErr As Double = msMea - msMascot
                        'Dim relErr As Double = 1000000.0 * absErr / msMascot
                        'If Math.Abs(relErr) > 7.5 Then
                        '    Dim peter20 As Integer = 20
                        'Else
                        '    doDump = False 'Don't dump unless rel error is high....
                        '    Dim peter03 As Integer = 3
                        'End If
                    End If

                    'Only needed for testing..
                    ''doDump = True 'Active: temp!!!!!!!!!!!!!!!!!!
                    'If mPept.AASequence = "LGVLGFFSTGDQHAR" Then
                    '    doDump = True
                    'End If

                    'Changed PM_DUMP_PERFORMANCE_MARKER 2004-06-25
                    doDump = False  'Activate for use in DTA SuperCharge - dumping
                    '  makes peakdetection extremely slow. Perhaps the
                    '  limit 210000 above should be parameter, to be set by
                    '  clients?

                    ''doDump = True 'Test only!!!!!!!!!!!!!

                    If doDump Then
                        'mDumpFileCounter
                        'mPept.AASequence
                        'mPept.calibratedMeasuredMZ
                        'mPept.charge
                        'mStr
                        Dim AASequence As String = anInfo.getAASequence()
                        Dim calibratedMeasuredMZ As Double = _
                          anInfo.getCalibratedMeasuredMZ()
                        Dim charge As Integer = anInfo.getCharge()

                        Dim str As String = _
                          dumpLCprofile(inSignal, _
                            anStartIndex, anEndIndex, _
                            anInOutDumpFileCounter, aSearchLevel, _
                            AASequence, calibratedMeasuredMZ, charge)
                        'Function name is a misnomer in this case...

                        anInfo.addToDumpString(str)
                        anInOutDumpFileCounter += 1
                    End If
                End If

                'Changed PM_OPTIMISATION 2004-12-17
                'Only get the signal once!
                'Dim someSignal As ArrayList = anInfo.getSignal()

                Dim maximumXDistanceForPeakDetection As Double = _
                  anInfo.getMaximumXDistanceForPeakDetection()
                Dim maximumXDistanceForMinima As Double = _
                  anInfo.getMaximumXDistanceForMinima()
                BSignal.findSignalPeak( _
                  inSignal, anStartIndex, anEndIndex, _
                  maximumXDistanceForPeakDetection, maximumXDistanceForMinima, _
                  outLCpeakTimeCentroid, outLCpeakIntensity, _
                  outLCPeakIndexStart, outLCPeakIndexEnd, _
                  outLCpeakWindowStart, outLCpeakWindowEnd, _
                  outLCMaxTime, outLCMaxIntensity, LCMaxIndex, _
                  backGround)

                Dim LCpointForMax As signalStructure = inSignal(LCMaxIndex)
                Dim leftLCpoint As signalStructure = inSignal(outLCpeakWindowStart)
                Dim rightLCpoint As signalStructure = inSignal(outLCpeakWindowEnd)

                Dim calibratedCentroidMass As Double = LCpointForMax.tagValue
                'mPept.MascotCalculatedMW
                Dim theoMass As Double = anInfo.getMascotCalculatedMW()
                'mPept.measuredMW
                'mPept.neutralMScentroidForLCMax
                'mPept.calibratedMeasuredMass
                Dim relError As Double = _
                  1000000.0 * (calibratedCentroidMass - theoMass) / theoMass
                Dim absRelError As Double = Math.Abs(relError)

                If backGround < 1.0 Then 'Avoid division by zero
                    backGround = 1
                End If
                Dim peakToBackgroundRatio As Double = _
                  outLCMaxIntensity / backGround

                'Changed PM_LCPEAK_MSMSEVENT 2004-02-02
                Dim MSMSeventInPeak As Boolean = False
                Dim MSMSretentionTimeSecs As Double = _
                  60.0 * anInfo.getMSMSretentionTimeMinutes()
                If anInfo.getConsiderMSMSevent() Then
                    If MSMSretentionTimeSecs >= leftLCpoint.Xsig AndAlso _
                       MSMSretentionTimeSecs <= rightLCpoint.Xsig Then

                        MSMSeventInPeak = True
                    End If
                End If

                Dim LCPeakInfo As LCPeakInfoStructure
                LCPeakInfo.maxIntensity = outLCMaxIntensity
                LCPeakInfo.calibratedNeutralMass = calibratedCentroidMass
                LCPeakInfo.absRelError_PPM = absRelError
                LCPeakInfo.peakToBackgroundRatio = peakToBackgroundRatio

                'Copy these fields. Needed by clients.
                LCPeakInfo.LCpeakTimeCentroid = outLCpeakTimeCentroid
                LCPeakInfo.LCpeakWindowStart = outLCpeakWindowStart
                LCPeakInfo.LCpeakWindowEnd = outLCpeakWindowEnd
                LCPeakInfo.LCMaxTime = outLCMaxTime
                LCPeakInfo.LCMaxIndex = LCMaxIndex
                LCPeakInfo.MSMSeventInPeak = MSMSeventInPeak

                'mLCPeakCandidates.Add(LCPeakInfo) 'Note: this is for the
                anInfo.addToPeakCandidates(LCPeakInfo) 'Note: this is for the
                '  peak in the middle interval.

                'To the left.
                Dim startIndex_left As Integer = anStartIndex
                Dim endIndex_left As Integer = outLCpeakWindowStart - 1
                internal_findThePeaks(anInfo, startIndex_left, endIndex_left, _
                  aSearchLevel + 1, _
                  anInOutDumpFileCounter)  'Recursive!

                'To the right.
                Dim startIndex_right As Integer = outLCpeakWindowEnd + 1
                Dim endIndex_right As Integer = anEndIndex
                internal_findThePeaks(anInfo, startIndex_right, endIndex_right, _
                  aSearchLevel + 1, _
                  anInOutDumpFileCounter)  'Recursive!
            End If

        End Sub 'internal_findThePeaks


        '****************************************************************************
        '*  SUBROUTINE NAME:   findThePeaksNonEx                                    *
        'd$ <summary>
        'd$   Purpose: Wrapper for findThePeaks() - few parameters.
        'd$            It also sorts the output peak list by X value, e.g. mass.
        'd$     Type of elements in anInSignal: signalStructure
        'd$   <see cref="T:VBXMLDoc.CVBXMLDoc" />.
        'd$ </summary>
        '  Later:
        '    Provide wrapper to this function 
        Public Shared Sub findThePeaksNonEx( _
          ByRef anInSignal As Generic.List(Of massSpectrometryBase.signalStructure), _
          ByRef anInOutPeakCandidates As Generic.List(Of LCPeakInfoStructure), _
          ByVal anInMaximumXDistanceForPeakDetection As Double, _
          ByVal anInMaximumXDistanceForMinima As Double, _
          ByVal anInFindPeaksMaxSearchLevel As Integer, _
          ByRef anInOutActualDeepestSearchLevel As Integer)

            'Old:
            '  ByRef anInSignal As ArrayList
            '  ByRef anInOutPeakCandidates As ArrayList


            Dim considerMSMSevent As Boolean = False
            Dim dumpCounter As Integer = 0
            Dim dumpStr As String = ""
            Dim doNotTriggerDump As Double = 111.1


            Dim lastIndex As Integer = anInSignal.Count - 1
            findThePeaks( _
                  anInSignal, _
                  0, _
                  lastIndex, _
                  considerMSMSevent, _
                  -10.0, _
                  doNotTriggerDump, _
                  anInOutPeakCandidates, _
                  dumpCounter, _
                  "XYZ", _
                  -5.0, _
                  -10.0, _
                  -1, _
                  dumpStr, _
                  anInMaximumXDistanceForPeakDetection, _
                  anInMaximumXDistanceForMinima, _
                  anInFindPeaksMaxSearchLevel, _
                  anInOutActualDeepestSearchLevel, _
                  1000000.0, _
                  0.5)

            Dim comp As New SortByX()
            anInOutPeakCandidates.Sort(comp)

        End Sub 'findThePeaksNonEx


        'Changed PM_REFACTOR 2004-06-22. Moved from FindLCpeaks.vb
        'Later: remove any reference to LC stuff...
        'Changed PM_BETTER_LCPEAK_DETECTION 2003-10-16
        '
        'Changed PM_DTASC_MEMORY 2004-10-15
        '  ByVal anAASequence -> ByRef anAASequence
        '
        '****************************************************************************
        '*  SUBROUTINE NAME:   findThePeaks                                         *
        'd$ <summary>
        'd$   Purpose: Find a candidate list of peaks. This is done by
        'd$            subdiving the interval XYZ.
        'd$     Type of elements in anInSignal: signalStructure
        'd$   <see cref="T:VBXMLDoc.CVBXMLDoc" />.
        'd$ </summary>
        '  Later:
        '    Provide wrapper to this function 
        Public Shared Sub findThePeaks( _
          ByRef anInSignal As _
            Generic.List(Of massSpectrometryBase.signalStructure), _
          ByVal anStartIndex As Integer, _
          ByVal anEndIndex As Integer, _
          ByVal aConsiderMSMSevent As Boolean, _
          ByVal aMSMSretentionTimeMinutes As Double, _
          ByVal aMaxY As Double, _
          ByRef anInOutPeakCandidates As Generic.List(Of LCPeakInfoStructure), _
          ByRef anInOutDumpFileCounter As Integer, _
          ByRef anInAASequence As String, _
          ByVal anCalibratedMeasuredMZ As Double, _
          ByVal aMascotCalculatedMW As Double, _
          ByVal aCharge As Integer, _
          ByRef anInOutDumpString As String, _
          ByVal anInMaximumXDistanceForPeakDetection As Double, _
          ByVal anInMaximumXDistanceForMinima As Double, _
          ByVal anInFindPeaksMaxSearchLevel As Integer, _
          ByRef anInOutActualDeepestSearchLevel As Integer, _
          ByVal aSegmentSize As Double, _
          ByVal aSegmentBoundaryValue As Double)

            'Old:
            '  ByRef anInSignal As ArrayList
            '  ByRef anInOutPeakCandidates As ArrayList


            Dim info As peaksInfoStorage = New peaksInfoStorage
            info.setSignal(anInSignal)
            info.setMaxY(aMaxY)
            info.setAASequence(anInAASequence)
            info.setCalibratedMeasuredMZ(anCalibratedMeasuredMZ)
            info.setCharge(aCharge)
            info.setMaximumXDistanceForPeakDetection(anInMaximumXDistanceForPeakDetection)
            info.setMaximumXDistanceForMinima(anInMaximumXDistanceForMinima)

            info.setMascotCalculatedMW(aMascotCalculatedMW)

            info.setMSMSretentionTimeMinutes(aMSMSretentionTimeMinutes)
            info.setConsiderMSMSevent(aConsiderMSMSevent)

            'Changed PM_OPTIMISATION 2004-12-17
            info.setFindPeaksMaxSearchLevel(anInFindPeaksMaxSearchLevel) 'Re-enable.....
            info.setActualDeepestSearchLevel(0)

            'Old.
            'internal_findThePeaks( _
            '  info, anStartIndex, anEndIndex, 0, anInOutDumpFileCounter)

            'aSegments
            Dim firstIndex As Integer = 0
            Dim lastIndex As Integer = anInSignal.Count - 1
            Dim firstSegmentLowerBound As Double
            Dim maxX As Double
            If True Then
                Dim firstPoint As signalStructure = anInSignal(firstIndex)
                Dim lastPoint As signalStructure = anInSignal(lastIndex)

                Dim minX As Double = firstPoint.Xsig
                maxX = lastPoint.Xsig

                firstSegmentLowerBound = aSegmentBoundaryValue

                'Find beginning af first segment.
                Dim done As Boolean = False
                While firstSegmentLowerBound > minX
                    firstSegmentLowerBound -= aSegmentSize
                End While

                'Binary search could be used here...
            End If

            Dim segmentLowerBound As Double = firstSegmentLowerBound
            Dim segmentUpperBound As Double = segmentLowerBound + aSegmentSize

            Dim startIndex As Integer = firstIndex

            Dim segmentCount As Integer = 0

            Dim sp As signalStructure
            Dim index As Integer = startIndex
            For Each sp In anInSignal
                Dim Xval As Double = sp.Xsig
                Dim atLastIndex As Boolean = index = lastIndex
                If Xval > segmentUpperBound Or atLastIndex Then

                    segmentCount += 1

                    Dim endIndex As Integer = index - 1
                    If atLastIndex Then
                        endIndex = index
                    End If

                    internal_findThePeaks( _
                      info, startIndex, endIndex, 0, anInOutDumpFileCounter)

                    startIndex = index

                    segmentLowerBound += aSegmentSize
                    segmentUpperBound = segmentLowerBound + aSegmentSize
                End If
                index += 1
            Next

            anInOutPeakCandidates = info.getPeakCandidates()
            anInOutDumpString = info.getDumpString()

            'Changed PM_OPTIMISATION 2004-12-17
            anInOutActualDeepestSearchLevel = info.getActualDeepestSearchLevel()
        End Sub 'findThePeaks


        'Changed PM_REFACTOR 2004-03-16
        '****************************************************************************
        '*  SUBROUTINE NAME:   dumpLCprofile                                        *
        'd$ <summary>
        'd$   Purpose: helper function for LC profiles....
        'd$ 
        'd$ 
        'd$     Type of elements in anInSignal: signalStructure
        'd$   <see cref="T:VBXMLDoc.CVBXMLDoc" />.
        'd$ </summary>
        Public Shared Function dumpLCprofile( _
          ByRef anInSignal As Generic.List(Of massSpectrometryBase.signalStructure), _
          ByVal anStartIndex As Integer, ByVal anEndIndex As Integer, _
          ByVal anInIDnumber As Integer, _
          ByVal aSearchLevel As Integer, _
          ByVal aPeptideSequence As String, _
          ByVal aCalibMCR As Double, _
          ByVal aCharge As Integer _
          ) _
          As String

            'Old:
            '  ByRef anInSignal As ArrayList


            Dim firstPoint As signalStructure = anInSignal(anStartIndex)
            Dim lastPoint As signalStructure = anInSignal(anEndIndex)

            Dim points As Integer = anInSignal.Count
            Dim str As String = _
              "LC profile (lower) dump " & anInIDnumber & "." & vbCr & vbLf & _
              points & " points" & vbCr & vbLf & _
              "Level: " & vbTab & aSearchLevel & vbCr & vbLf & _
              "Indices: " & vbTab & "[" & vbTab & anStartIndex & vbTab & ";" & _
                vbTab & anEndIndex & vbTab & "]" & vbCr & vbLf & _
              "Mass range: " & vbTab & "[" & vbTab & firstPoint.Xsig & vbTab & ";" & _
                vbTab & lastPoint.Xsig & vbTab & "] Da" & vbCr & vbLf & _
              "Sequence: " & vbTab & aPeptideSequence & vbCr & vbLf & _
              "Calibrated measured MCR: " & vbTab & aCalibMCR & vbCr & vbLf & _
              "Charge: " & vbTab & aCharge & vbCr & vbLf & _
              vbCr & vbLf

            str &= "Index" & vbTab & _
                   "Cycle" & vbTab & _
                   "LC time [secs]" & vbTab & _
                   "LC signal" & vbTab & _
                   "Calibrated neutral MS centroid mass" & vbTab & _
                   vbCr & vbLf
            Dim sIndex As Integer = 0
            Dim sPoint As signalStructure
            For Each sPoint In anInSignal
                If sIndex >= anStartIndex AndAlso sIndex <= anEndIndex Then
                    str &= _
                      sIndex & vbTab & _
                      sPoint.tagValue2 & vbTab & _
                      sPoint.Xsig & vbTab & _
                      sPoint.Ysig & vbTab & _
                      sPoint.tagValue & vbTab & _
                      vbCr & vbLf
                End If
                sIndex += 1
            Next
            str &= "END_OF_DUMP" & vbCr & vbLf & _
              "============================================" & vbCr & vbLf

            Return str
        End Function 'dumpLCprofile


        'Changed PM_REFACTOR 2005-01-05
        'Moved to here from DTASC' peakutil.vb.
        '****************************************************************************
        '*    <placeholder for header>                                              *
        '*      Type is: signalStructure                                            *
        '****************************************************************************
        Public Shared Sub filterSignalByMassRange( _
          ByRef anInSignal As Generic.List(Of massSpectrometryBase.signalStructure), _
          ByVal aStartMass As Double, ByVal anEndMass As Double, _
          ByRef anOutSignal As Generic.List(Of massSpectrometryBase.signalStructure), _
          ByRef anOutMaxY As Double)

            'Old:
            '  ByRef anInSignal As ArrayList
            '  ByRef anOutSignal As ArrayList


            'anOutMaxY: we don't use dataPointsInfoStructure2 as it would drag in
            '  too many fields.

            anOutMaxY = -1.0E+20

            'Type of aSignal: signalStructure
            'anOutSignal = New ArrayList
            anOutSignal = New Generic.List(Of massSpectrometryBase.signalStructure)

            If True Then
                Dim someSignal As signalStructure
                For Each someSignal In anInSignal
                    Dim someMass As Double = someSignal.Xsig
                    If someMass >= aStartMass AndAlso someMass <= anEndMass Then
                        anOutSignal.Add(someSignal)
                        If someSignal.Ysig > anOutMaxY Then
                            anOutMaxY = someSignal.Ysig
                        End If
                    End If
                Next
            End If
        End Sub 'filterSignalByMassRange


        '****************************************************************************
        '*  SUBROUTINE NAME:   convertListTo_signalStructureList                    *
        'd$ <summary>
        'd$   Purpose: convert a list of LCPeakInfoStructure to list
        'd$            of signalStructure.
        'd$   <see cref="T:VBXMLDoc.CVBXMLDoc" />.
        'd$ </summary>
        Public Shared Function convertListTo_signalStructureList( _
          ByRef anInList As Generic.List(Of LCPeakInfoStructure)) _
          As Generic.List(Of massSpectrometryBase.signalStructure)

            'Old return type:
            '  ArrayList
            '  ByRef anInList As ArrayList


            Dim inputSize As Integer = anInList.Count

            'Dim outList As ArrayList = New ArrayList
            Dim outList As _
              Generic.List(Of massSpectrometryBase.signalStructure) = _
                New Generic.List(Of massSpectrometryBase.signalStructure)(inputSize)
            '  Output size is exactly the same as the input size.

            Dim someSignal As LCPeakInfoStructure
            For Each someSignal In anInList
                Dim someNewItem As signalStructure
                someNewItem.Xsig = someSignal.LCMaxTime
                someNewItem.Ysig = someSignal.maxIntensity
                outList.Add(someNewItem)
            Next

            Trace.Assert(outList.Count = inputSize, _
              "PIL ASSERT. convertListTo_signalStructureList is not the " & _
              "excepted, in convertListTo_signalStructureList().")

            Return outList
        End Function 'convertListTo_signalStructureList


        'Changed PM_MS3SCORING_ISOTOPE_ELIMINATION 2005-01-21
        '****************************************************************************
        '*  SUBROUTINE NAME:   simpleIsotopeElimination                             *
        'd$ <summary>
        'd$   
        'd$   Purpose: elimination of isotope peaks using very simple rules: C13
        'd$     peaks are eliminated if there is a lower (low mass fragments
        'd$     assumed). The input is assumed to be reduced (peaklist), not
        'd$     raw data.
        'd$     Note: designed for fragment spectra as isotope patterns are
        'd$           assumed to be low mass (not multiple charged at the lower
        'd$           mass-to-charge ratio).
        'd$ 
        'd$     Real type in lists: LCPeakInfoStructure
        'd$   <see cref="T:VBXMLDoc.CVBXMLDoc" />.
        'd$ </summary>
        Public Shared Function simpleIsotopeElimination( _
          ByRef anInList As Generic.List(Of LCPeakInfoStructure)) _
          As Generic.List(Of LCPeakInfoStructure)

            'Changed PM_TYPESAFE 2006-11-01
            'Old: 
            '  ByRef anInList As ArrayList
            '
            '  Return type:
            '    ArrayList


            'Changed PM_TYPESAFE 2006-11-
            'Dim toReturn As ArrayList = New ArrayList
            Dim inputSize As Integer = anInList.Count
            Dim toReturn As Generic.List(Of LCPeakInfoStructure) = _
              New Generic.List(Of LCPeakInfoStructure)(inputSize)
            '   Capacity: it will be smaller than the input, but it is probably
            '   better than multiple resizes.

            Dim len As Integer = anInList.Count
            Dim lastIndex As Integer = len - 1
            Dim include(lastIndex) As Boolean

            Dim tolerance As Double = 0.22
            Dim peptideUniDistance As Double = 1.00234565
            Dim diffLow As Double = peptideUniDistance - tolerance
            Dim diffHigh As Double = peptideUniDistance + tolerance


            Dim eliminatedCount As Integer = 0
            Dim index As Integer = 0
            Dim someSignal As LCPeakInfoStructure
            For Each someSignal In anInList
                'someNewItem.Xsig = someSignal.LCMaxTime
                'someNewItem.Ysig = someSignal.maxIntensity

                include(index) = True

                'Search back to see if there were any peak at the expected distance with a higher intensity.
                Dim mass As Double = someSignal.LCMaxTime
                'Dim massLow As Double = mass - diffHigh
                'Dim massHigh As Double = mass - diffLow

                Dim sIndex As Integer = index - 1
                Dim done As Boolean = False
                While (Not done)
                    If sIndex >= 0 Then
                        Dim massPrev As Double = _
                          anInList(sIndex).LCMaxTime
                        Dim massDiff As Double = mass - massPrev
                        If massDiff > diffHigh Then
                            'We are past the mass window. Stop.
                            done = True
                        Else
                            If massDiff >= diffLow AndAlso massDiff <= diffHigh Then
                                Dim y As Double = someSignal.maxIntensity

                                'Some peak in the window.
                                Dim prevY As Double = _
                                  anInList(sIndex).maxIntensity

                                Dim intensityRatio As Double = y / prevY
                                If intensityRatio < 1.0 Then 'First condition: previous peak
                                    '  must be higher. Implicit we assume there are only low
                                    '  mass single charged ions.

                                    If intensityRatio > 0.1 AndAlso intensityRatio < 0.8 Then
                                        include(index) = False
                                        eliminatedCount += 1
                                    End If
                                End If
                            End If
                        End If
                    Else
                        done = True 'Outside array bounds.
                    End If
                    sIndex -= 1
                End While
                index += 1
            Next

            'Read-out
            index = 0
            For Each someSignal In anInList
                If include(index) Then
                    toReturn.Add(someSignal)
                End If
                index += 1
            Next

            Return toReturn
        End Function 'simpleIsotopeElimination


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '*                                                                          *
        '*   Given a centroided peak list or raw data, we give back a list          *
        '*   of the four                                                            *
        '*   highest intensity peaks per hundred Da (storing only the indices).     *
        '*   Right now we can have four values for the first and last interval      *
        '*   even if it is very small. Need to fix.                                 *
        '*                                                                          *
        '****************************************************************************
        Public Shared Sub reducePeakList2( _
          ByRef anInSignal As Generic.List(Of massSpectrometryBase.signalStructure), _
          ByRef anOutPeakLst() As Integer, _
          ByRef anOutEffectiveDataPoints As Generic.List(Of LCPeakInfoStructure), _
          ByVal aMaxSearchLevel As Integer, _
          ByVal aMassWindow As Double, _
          ByVal aKeepCount As Integer, _
          ByVal aCatchDistance As Double)

            'Old:
            '  ByRef anInSignal As ArrayList
            '  ByRef anOutEffectiveDataPoints As ArrayList
            '
            '  ByRef aDataPtInfoStr_toDelete As dataPointsInfoStructure2, _


            'Find peaks in the MS spectrum. 


            'Changed PM_USERSET_MS3_MATCHING_TOLERANCE 2007-07-13
            'Dim massWindow As Double = 100.0
            Dim massWindow As Double = aMassWindow


            'Changed PM_TYPESAFE 2006-11-01
            'anOutEffectiveDataPoints = New ArrayList
            anOutEffectiveDataPoints = New Generic.List(Of LCPeakInfoStructure)
            If True Then

                'Changed PM_TYPESAFE 2006-11-01
                'Dim initialPeakList As ArrayList = Nothing 'Keep compiler happy.
                Dim initialPeakList As Generic.List(Of LCPeakInfoStructure) = _
                  Nothing 'Keep compiler happy.

                'Changed PM_CODEMARKER_0.3DA_CATCHDISTANCE 2006-11-22
                'Dim catchDistance As Double = 0.03 'Bigger peaks will not...
                Dim catchDistance As Double = 0.3 'Bigger peaks will not 
                '  svallow smaller ones, even if the data is already centroided.


                'Changed PM_USERSET_MS3_MATCHING_TOLERANCE 2007-07-13
                catchDistance = aCatchDistance


                'Changed PM_MS3SCORING_LOWER_CATCHDISTANCE 2005-01-21
                'Dim catchDistanceForExtension As Double = 1.1
                Dim catchDistanceForExtension As Double = 0.4

                'Dim findPeaksMaxSearchLevel As Integer = 99  now a parameter..
                Dim actualDeepestSearchLevel As Integer

                BSignal.findThePeaksNonEx( _
                  anInSignal, _
                  initialPeakList, _
                  catchDistance, catchDistanceForExtension, _
                  aMaxSearchLevel, actualDeepestSearchLevel)

                'Changed PM_MS3SCORING_ISOTOPE_ELIMINATION 2005-01-21
                anOutEffectiveDataPoints = _
                  BSignal.simpleIsotopeElimination(initialPeakList)
            End If

            Dim lastIndex2 As Integer = anOutEffectiveDataPoints.Count - 1

            Dim outSize As Integer = 0
            Dim low100 As Double = 0
            Dim high100 As Double = -100
            If lastIndex2 >= 0 Then 'It can be -1 if the spectrum
                '  is empty. This can be the case if XCalibur 2.0 is
                '  installed and an older LTQ-FT file is open.....
                Dim minX As Double = _
                  anOutEffectiveDataPoints(0).LCpeakTimeCentroid
                Dim maxX As Double = _
                  anOutEffectiveDataPoints(lastIndex2).LCpeakTimeCentroid

                'Changed PM_MS3SCORING_USEPEAKS 2004-10-27
                'Dim low100 As Double = 100 * Math.Floor(aDataPtInfoStr.minX2 / 100.0)
                'Dim high100 As Double = 100 * Math.Ceiling(aDataPtInfoStr.maxX2 / 100.0)
                low100 = massWindow * Math.Floor(minX / massWindow)
                high100 = massWindow * Math.Ceiling(maxX / massWindow)

                outSize = _
                  CInt(Math.Round(aKeepCount * (high100 - low100) / massWindow))
            End If

            ReDim anOutPeakLst(outSize) 'Up to
            '  four peaks per massWindow Da.

            Dim j As Integer 'Indices for the signal structures
            '  in this massWindow Da range.

            Dim theLowMass As Double = 0.0
            Dim iHighMass As Integer = 0
            Dim iLowMass As Integer = 0

            Dim numIons As Integer = 0

            Dim lastIndexArr As Integer = aKeepCount - 1
            Dim tempArr(lastIndexArr) As Integer 'Keep the indices
            '  within massWindow Da range.

            For theLowMass = low100 To high100 Step massWindow

                'Changed PM_MANNREDUCTION_LEVEL 2005-09-05
                'tempArr(0) = -1
                'tempArr(1) = -1
                'tempArr(2) = -1
                'tempArr(3) = -1
                Dim i As Integer
                For i = 0 To lastIndexArr Step 1
                    tempArr(i) = -1
                Next i

                'Set the index for the higher mass.
                Dim upperMassInInterval As Double = theLowMass + massWindow

                'Changed PM_MS3SCORING_USEPEAKS 2004-10-27
                'While iHighMass < inSignArr.Count AndAlso _
                '  DirectCast(inSignArr(iHighMass), signalStructure).Xsig <= _
                '    upperMassInInterval
                While iHighMass < anOutEffectiveDataPoints.Count AndAlso _
                  anOutEffectiveDataPoints(iHighMass).LCpeakTimeCentroid <= _
                    upperMassInInterval

                    iHighMass += 1
                End While

                'Run through the array four times, determining the  
                'highest remaining value each time.
                'Should be fast enough and we don't need to do complicated
                'array sorts.
                Dim k As Integer
                Dim lastIndex As Integer = iHighMass - 1
                For k = 0 To lastIndexArr
                    Dim highSignVal As Double = Double.MinValue
                    For j = iLowMass To lastIndex
                        Dim y As Double = _
                          anOutEffectiveDataPoints(j).maxIntensity

                        'Changed PM_MANNREDUCTION_LEVEL 2005-09-05
                        Dim allDifferent As Boolean = True
                        For i = 0 To lastIndexArr Step 1
                            If tempArr(i) = j Then
                                allDifferent = False
                            End If
                        Next i
                        '
                        'If y > highSignVal AndAlso _
                        '  tempArr(0) <> j AndAlso _
                        '  tempArr(1) <> j AndAlso _
                        '  tempArr(2) <> j AndAlso _
                        '  tempArr(3) <> j Then
                        If y > highSignVal AndAlso _
                          allDifferent Then

                            highSignVal = y
                            tempArr(k) = j
                        End If
                    Next j
                Next k
                iLowMass = iHighMass 'Rachet up the lower index to iHighMass which
                'is already in the next massWindow.

                'Now append the values in tempArr to outPeakLst.
                For k = 0 To lastIndexArr
                    If tempArr(k) <> -1 Then
                        anOutPeakLst(numIons) = tempArr(k)
                        numIons += 1
                    End If
                Next
            Next 'next theLowMass

            ReDim Preserve anOutPeakLst(numIons - 1)
            Array.Sort(anOutPeakLst) 'It is sufficient to sort the indices.
        End Sub 'reducePeakList


    End Class 'BSignal


End Module 'signalModule


    

    

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