Source code for MSQuant: peptideFragments.vb, MSQuant/msquant/src/main/massbase/peptideFragments.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: Holds Class fragments, see below for documentation.             *
'*                                                                          *
'****************************************************************************

'****************************************************************************
'*                               CEBI                                       *
'*                    Software Development Group                            *
'*                         Peter Mortensen                                  *
'*                E-mail: NUKESPAMMERSdrmortensen@get2netZZZZZZ.dk          *
'*                 WWW: http://www.cebi.sdu.dk/                             *
'*                                                                          *
'*  Program for ........                                                    *
'*                                                                          *
'*    FILENAME:   peptideFragments.vb                                       *
'*    TYPE:       VISUAL_BASIC                                              *
'*                                                                          *
'* CREATED: PM 2005-02-22   Vrs 1.0.                                        *
'* UPDATED: PM 2005-xx-xx                                                   *
'*                                                                          *
'****************************************************************************

Option Strict On
Option Explicit On 

Imports System.Text  'For StringBuilder
Imports System.Collections.Generic 'For Dictionary


Imports MolecularSharedStructures 'For modificationCountStructure.
Imports massSpectrometryBase.quantitation 'For QuantitationModes_moreGeneral.


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

    'Changed PM_REFACTOR 2008-05-10. Moved to file PILgeneralisedIonSeries.cs.
    ' 'Changed PM_DTASC_COMPILE 2006-07-04. Moved here to avoid
    ' 'dependency in DTASC.
    ' Public Structure ionSetStructure
    '     Dim forwardIonDiffs() As Double
    '     Dim backwardIonDiffs() As Double
    ' 
    '     Dim compVectorIndex As Integer 'Index into list of combItemStructure
    ' 
    '     Dim ID As Integer 'So client can later return to a return item.
    ' 
    '     Dim score As Double 'Dragged along here. For convenience.
    ' End Structure 'ionSetStructure


    '****************************************************************************
    '*    <placeholder for header>                                              *
    '****************************************************************************
    Class SortDisplItemsByCalcMass
        Implements IComparer
        Private Function Compare(ByVal x As Object, ByVal y As Object) _
        As Integer Implements System.Collections.IComparer.Compare

            Dim item1 As fragmentExStructure = CType(x, fragmentExStructure)
            Dim item2 As fragmentExStructure = CType(y, fragmentExStructure)
            Return Math.Sign(item1.MCRcalcLoc - item2.MCRcalcLoc)
        End Function
    End Class 'SortDisplItemsByCalcMass


    '****************************************************************************
    'd$ <summary>
    'd$   Purpose: handles calculation of properties for peptide ions 
    'd$            It is on a higher level than, xyz() and is closer to 
    'd$            what can be oberved in a real spectrum - it handles proline
    'd$            annotation, recalibration, double charged y ions, a2 ion,
    'd$            charged precursor as a ion.
    'd$            And there are functions: mass matching, text output/report,
    'd$            
    'd$              Has state, e.g. the fragments. Operations on fragments can be: matching a given mass to a fragment, ...
    'd$ 
    'd$ 
    'd$   <see cref="T:VBXMLDoc.CVBXMLDoc" />.
    'd$   <applicationname>test_rawDataFileHandling</applicationname>
    'd$   <author>Peter Mortensen</author>
    'd$   <seealso>http://www.cebi.sdu.dk/</seealso>
    'd$   <codetype>PLATFORM independent / GUI</codetype>
    'd$ </summary>
    Public Class peptideFragments

        Private mDisplItmArr1() As fragmentExStructure 'Theoretical fragment information including
        '  helper fields for ms3 scoring, etc. Real type is: fragmentExStructure.

        'Changed PM_REFACTOR 2007-10-29
        'Private mB As Double
        'Private mA As Double
        Private mRecalibrator As SDUPrecalibrator


        'Changed PM_ALSO_PRECURSOR_FOR_MS3 2006-10-31
        'Dim mQuantModeCode As Integer
        Private mQuantitationModesObject As QuantitationModes_moreGeneral

        'Changed PM_REFACTOR 2007-03-16
        'Private mSILACmods As Hashtable
        Private mSILACmods2 As Dictionary(Of Integer, Boolean)

        Private mPeptideSequence As String
        Private mCurrentlyZoomedFrag As Integer 'Name to be changed to: mReadIndex


        'Changed PM_GENERALISED_IONSERIES 2008-05-09
        Dim mPILgeneralisedIonSeries As PILgeneralisedIonSeries


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub New( _
          ByRef anInCalibration As SDUPrecalibrator, _
          ByRef anInQuantitationModesObject As QuantitationModes_moreGeneral, _
          ByRef aQuantModeCode As Integer, _
          ByRef anInPILgeneralisedIonSeries As PILgeneralisedIonSeries)

            'Changed PM_REFACTOR 2007-10-29
            'Old:
            '  ByVal aCalibSlope As Double, ByVal aCalibOffset As Double

            'Changed PM_REFACTOR 2007-10-30
            'mB = aCalibSlope
            'mA = aCalibOffset
            mRecalibrator = anInCalibration

            'Changed PM_ALSO_PRECURSOR_FOR_MS3 2006-10-31
            'mQuantModeCode = aQuantModeCode
            mQuantitationModesObject = anInQuantitationModesObject

            mSILACmods2 = _
              anInQuantitationModesObject.modificationIDsForQuantitationMode( _
                aQuantModeCode)

            'Changed PM_GENERALISED_IONSERIES 2008-05-09
            mPILgeneralisedIonSeries = anInPILgeneralisedIonSeries


            'Changed PM_REFACTOR 2007-10-30. In new class.
            'Trace.Assert(mB > 0.9 AndAlso mB < 1.1, _
            '  "PIL ASSERT. aRecalibSlope is outside a reasonable range. Value: " & _
            '  mB)

            'Changed PM_ALWAYSSHOW_BEST_MS3_MATCH 2006-03-03
            Me.reset()
        End Sub 'New


        'Is this really needed? Yes, at least if we use it to also reset
        'the read pointer.
        'It used by clients when moving to another protein.
        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub reset()
            If Not mDisplItmArr1 Is Nothing Then
                Array.Clear(mDisplItmArr1, 0, mDisplItmArr1.Length)
            End If

            Me.resetRead()
        End Sub 'reset


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function fragments() As Integer
            Return mDisplItmArr1.Length
        End Function 'fragments


        'Use normal array instead of ArrayList?
        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getFragmentTokens( _
          ByVal aStartMCR As Double, ByVal anEndMCR As Double) _
          As ArrayList

            Trace.Assert(aStartMCR > 40.0, _
                         "PIL ASSERT. aStartMCR is undefined. Value: ." & aStartMCR)
            Trace.Assert(anEndMCR > 40.0, _
                         "PIL ASSERT. anEndMCR is undefined. Value: ." & anEndMCR)

            Dim toReturn As ArrayList = New ArrayList
            Dim i As Integer
            Dim lastIndex As Integer = mDisplItmArr1.Length - 1
            For i = 0 To lastIndex
                With mDisplItmArr1(i)
                    Dim MCRCalcLoc As Double = .MCRcalcLoc

                    '30.0: to ignore the zero mass fragment at the beginning...
                    If MCRCalcLoc > aStartMCR AndAlso MCRCalcLoc < anEndMCR AndAlso _
                       MCRCalcLoc > 30.0 Then

                        'Currently a token happens to be the array index, but
                        'this could change...
                        toReturn.Add(i)
                    End If
                End With
            Next
            Return toReturn
        End Function 'getFragmentTokens


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function getFragment(ByVal aToken As Integer) As fragmentExStructure

            'Currently a token happens to be the array index, but this could change...
            Return mDisplItmArr1(aToken) 'Why does this not require a cast??
        End Function 'getFragment


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        'Private for now..
        Private Sub resetRead()
            mCurrentlyZoomedFrag = 0
        End Sub 'resetRead


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub readStateMiddleFragment()
            mCurrentlyZoomedFrag = CInt(Me.fragments() / 2)
        End Sub 'readStateMiddleFragment


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub resetMarkMatches()

            'Changed PM_FRAGMENTDISPLAY 2008-05-18. Needed to have it work
            '  for the first displayed peptide... We changed the order of calls... 
            If Not mDisplItmArr1 Is Nothing Then
                Dim i As Integer
                Dim lastIndex As Integer = mDisplItmArr1.Length - 1
                For i = 0 To lastIndex
                    mDisplItmArr1(i).ionMatched = False
                Next
            End If

        End Sub 'resetMarkMatches


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub markMatch(ByVal aToken As Integer, ByVal aMatched As Boolean)

            'Currently a token happens to be the array index, but this could change...
            mDisplItmArr1(aToken).ionMatched = aMatched
        End Sub 'readStateMiddleFragment


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function fragmentsMatchedCount() As Integer

            Dim count As Integer = 0
            Dim i As Integer
            Dim lastIndex As Integer = mDisplItmArr1.Length - 1
            For i = 0 To lastIndex
                If mDisplItmArr1(i).ionMatched Then
                    count += 1
                End If
            Next
            Return count
        End Function 'DetermineNumFragInMassRange


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function lightestFragmentMCR() As Double

            Dim toReturn As Double = 0.0

            Dim i As Integer
            Dim lastIndex As Integer = mDisplItmArr1.Length - 1
            'There are normally only 0 or 1 iterations in this loop.
            For i = 0 To lastIndex
                Dim MCR As Double = mDisplItmArr1(i).MCRcalcLoc
                If MCR > 30.0 Then
                    toReturn = MCR
                    Exit For
                End If
            Next
            Return toReturn
        End Function 'lightestFragmentMCR


        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function heaviestFragmentMCR() As Double

            Dim lastIndex As Integer = mDisplItmArr1.Length - 1
            Dim toReturn As Double = mDisplItmArr1(lastIndex).MCRcalcLoc
            Trace.Assert(toReturn < 1000000.0, _
              "PIL ASSERT. Highest fragment mass is too high....: " & toReturn)
            Trace.Assert(toReturn > 10.0, _
              "PIL ASSERT. Highest fragment mass is too low....: " & toReturn)

            Return toReturn
        End Function 'heaviestFragmentMCR


        'Currently no EOF, wraps around...
        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function nextFragment() As fragmentExStructure
            If mCurrentlyZoomedFrag >= Me.fragments() - 1 Then
                mCurrentlyZoomedFrag = 0
            Else
                mCurrentlyZoomedFrag += 1
            End If
            Return mDisplItmArr1(mCurrentlyZoomedFrag)
        End Function 'nextFragment


        'Currently no EOF, wraps around...
        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function previousFragment() As fragmentExStructure

            If mCurrentlyZoomedFrag <= 0 Then
                'Start with the top fragment again.
                mCurrentlyZoomedFrag = Me.fragments() - 1
            Else
                mCurrentlyZoomedFrag -= 1
            End If
            Return mDisplItmArr1(mCurrentlyZoomedFrag)
        End Function 'previousFragment


        'Changed PM_GENERALISED_IONSERIES 2008-05-09. Old function for 
        '  reference until we know the new generalised way works.
        '
        ' 'MM changed for MS3 2004-04-25
        ' 'Added a parameter for Bions, so that we have the correct display
        ' 'structure for bions use the optional argument so that nothing
        ' 'gets disrupted. Provide flag for case MS3 Bion.
        ' '****************************************************************************
        ' '*    <placeholder for header>                                              *
        ' '*   anInModificationsList: type is simpleModificationSpecification         *
        ' '****************************************************************************
        ' Public Sub CalcFragIons_old( _
        '   ByVal aSeq As String, _
        '   ByVal aSeqIsRealPeptide As Boolean, _
        '   ByVal aPeptideSequence As String, _
        '   ByVal aPrecursorCharge As Integer, _
        '   ByRef anInModificationsList As _
        '     Generic.List(Of Generic.List(Of quantitation.AAsetStructure)), _
        '   ByRef anInPeptModStr As String, _
        '   ByRef anInMassAdjustments As ionSetStructure, _
        '   ByRef aModifications As Generic.List(Of modificationCountStructure), _
        '   Optional ByVal aMS3_Bion As Boolean = False)
        '
        '     'To eliminate: anInPeptModStr
        '
        '     'Changed PM_PERFILE_RECALIBRATION 2007-11-16
        '     Dim recalibTag As Integer = SDUPrecalibrator.ALL_TAGCODE 'For now;
        '     '  for all files.
        '     '
        '     '  In any case it is incorrect in general to use the same
        '     '  recalibration for MS and MS-MS (e.g. hybrid instruments
        '     '  like LTQ-FT or Orbitrap).
        '
        '     'What is the difference between aSeq and aPeptideSequence ??????
        '     'aSeq is used for the computations.
        '
        '     Trace.Assert(aPrecursorCharge > 0, _
        '       "PIL ASSERT. precursor charge is improper: ." & aPrecursorCharge)
        '
        '     mPeptideSequence = aPeptideSequence
        '
        '     Dim pepLen As Integer = aSeq.Length
        '     Dim lastPepIndex As Integer = pepLen - 1
        '
        '     'Changed PM_PHOSPHO_SCORING 2005-08-09
        '     Dim useMassAdjustment As Boolean = _
        '       Not anInMassAdjustments.backwardIonDiffs Is Nothing
        '
        '     'ArrayList of display objects with the following: MCR Loc, sequence,
        '     'descriptor string,
        '
        '     Dim yArr() As Double
        '     Dim bArr() As Double
        '     ReDim yArr(lastPepIndex)
        '     ReDim bArr(lastPepIndex)
        '
        '     Dim maxIdxY As Integer
        '     Dim maxIdxB As Integer
        '
        '     Dim modStrToUse As String = anInPeptModStr
        '
        '     If modStrToUse = "" Then
        '         modStrToUse = "Carbamidomethyl (C)"
        '     End If
        '
        '     'PM: why not pass aMS3_Bion and have only one call?
        '     If aMS3_Bion = False Then
        '         MMaaSequence.yIonArray( _
        '           aSeq, yArr, maxIdxY, modStrToUse, anInModificationsList)
        '     Else 'We have to calculate MS3 ions from a b-ion precursor.
        '         MMaaSequence.yIonArray( _
        '           aSeq, yArr, maxIdxY, modStrToUse, anInModificationsList, True)
        '     End If
        '
        '     MMaaSequence.bIonArray( _
        '       aSeq, bArr, maxIdxB, modStrToUse, anInModificationsList)
        '
        '     'Changed PM_PHOSPHO_SCORING 2005-08-09
        '     'Make the mass adjustment at this point. The alternative would
        '     'be to do it in MMaaSequence. More cyclic dependence?
        '     If useMassAdjustment Then
        '
        '         Dim backwardIonLen As Integer = _
        '           anInMassAdjustments.backwardIonDiffs.GetLength(0)
        '
        '         Trace.Assert(pepLen = backwardIonLen, _
        '           "PIL ASSERT. Peptide length, " & pepLen & _
        '           ", does not correspond to number of backward (y) ions," & _
        '           backwardIonLen & ".")
        '
        '         'Changed PM_BAD_PRECURSORMASS 2006-10-31
        '         ''Extra -1: the bN ion and the yN ion corresponding to the peptide
        '         ''          are not computed/used.
        '         'Dim internalBackwardLen As Integer = backwardIonLen - 1 - 1
        '         Dim internalBackwardLen As Integer = backwardIonLen - 1
        '
        '         Trace.Assert( _
        '           internalBackwardLen = maxIdxY, _
        '           "PIL ASSERT. Backward ions: adjusted number of ions, " & _
        '           internalBackwardLen & _
        '           ", does not correspond to size of internal datastructure " & _
        '           "for backward (y) ions," & maxIdxY & ".")
        '
        '         Dim forwardIonLen As Integer = _
        '           anInMassAdjustments.backwardIonDiffs.GetLength(0)
        '         Dim internalforwardLen As Integer = forwardIonLen - 1 - 1
        '         Trace.Assert( _
        '           internalforwardLen = maxIdxB, _
        '           "PIL ASSERT. Forward ions: adjusted number of ions, " & _
        '           internalforwardLen & _
        '           ", does not correspond to size of internal datastructure " & _
        '           "for forward (b) ions," & maxIdxB & ".")
        '
        '         Dim lowerMassLimit As Double = 56.0 'Slightly less than G/Gly.
        '
        '         Dim prevMass As Double = 0.0
        '         Dim j As Integer
        '         For j = 0 To maxIdxY
        '             Dim effectiveIndex As Integer = lastPepIndex - j
        '             Dim offsetMass As Double = _
        '               anInMassAdjustments.backwardIonDiffs(effectiveIndex)
        '
        '             Dim oldMass As Double = yArr(j) 'For easier debugging.
        '             Dim newMass As Double = oldMass + offsetMass
        '             yArr(j) = newMass
        '
        '             Dim massDiff As Double = newMass - prevMass
        '             Trace.Assert(massDiff > lowerMassLimit, _
        '               "PIL ASSERT. Impossible low mass for amino acid """ & _
        '               aSeq.Substring(effectiveIndex, 1) & _
        '               """ in peptide " & aSeq & " (position " & _
        '               (effectiveIndex + 1) & _
        '               "): " & massDiff & " Da (limit: " & _
        '               lowerMassLimit & " Da). y-ion series." _
        '               )
        '             prevMass = newMass
        '         Next j
        '
        '         prevMass = 0.0
        '         For j = 0 To maxIdxB
        '             Dim effectiveIndex As Integer = j
        '             Dim offsetMass As Double = _
        '               anInMassAdjustments.forwardIonDiffs(effectiveIndex)
        '
        '             Dim oldMass As Double = bArr(j) 'For easier debugging.
        '             Dim newMass As Double = oldMass + offsetMass
        '             bArr(j) = newMass
        '
        '             Dim massDiff As Double = newMass - prevMass
        '             Trace.Assert(massDiff > lowerMassLimit, _
        '               "PIL ASSERT. Impossible low mass for amino acid """ & _
        '               aSeq.Substring(effectiveIndex, 1) & _
        '               """ in peptide " & aSeq & " (position " & _
        '               (effectiveIndex + 1) & _
        '               "): " & massDiff & " Da (limit: " & _
        '               lowerMassLimit & " Da). b-ion series." _
        '               )
        '             prevMass = newMass
        '         Next j
        '     End If
        '
        '     ReDim mDisplItmArr12(3 * maxIdxY + 10) 'HACK: display b,y and y++,
        '     '  MCR and some others.
        '
        '     'Fill array and then sort by calculated MCR value.
        '     Dim i As Integer
        '     Dim disItem As fragmentExStructure
        '     Dim arrIdx As Integer = 0
        '
        '     'y ions.
        '     Dim yNindex As Integer = -1
        '     For i = 0 To maxIdxY
        '         With disItem
        '             .charge = 1
        '
        '             'Since we don't recalibrate the raw data we must adjust here.
        '             'Definition: calc MCR = mA + mB MCR observed.
        '
        '             'Changed PM_MARKER_MSRECALIB_FOR_FRAGMENTS 2007-10-30
        '             'Why do we use MS recalibration for MS/MS data??? For
        '
        '             'Changed PM_REFACTOR 2007-10-30
        '             'If Not mB < 0.2 Then
        '             '    .MCRcalcLoc = (yArr(i) - mA) / mB
        '             'Else
        '             '    .MCRcalcLoc = yArr(i)
        '             'End If
        '             Dim yMass As Double = yArr(i)
        '             If mRecalibrator.calibrationIsDefined() Then
        '
        '                 'Note: this is for MS-MS, but we are using the
        '                 '      precursor (MS) calibration... It may be OK
        '                 '      for QSTAR, but definitely not for LTQ-FT where
        '                 '      the two types of spectra are recorded by two
        '                 '      completely different instruments. Fortunately
        '                 '      the error level is much lower for FT than for LTQ.
        '                 .MCRcalcLoc = _
        '                   mRecalibrator.calib2uncalib(yMass, recalibTag)
        '             Else
        '                 .MCRcalcLoc = yMass
        '             End If
        '
        '             .descStr = "y" & (i + 1).ToString
        '             .seq = aSeq.Remove(0, maxIdxY - i)
        '             .ionType = ionTypeEnum.enumYion
        '
        '             'Check for proline feature.
        '             If i > 0 AndAlso _
        '                (Math.Abs((yArr(i) - yArr(i - 1)) - PRO_MONO_MASS)) < 0.01 Then
        '                 .descStr = "P " & .descStr
        '             End If
        '         End With
        '         mDisplItmArr12(arrIdx) = disItem
        '
        '         'yN
        '         If i = maxIdxY Then
        '             yNindex = arrIdx
        '         End If
        '
        '         arrIdx += 1
        '     Next i 'y ions
        '
        '     'y++ ions
        '     For i = 0 To maxIdxY
        '
        '         'Changed PM_Y_DOUBLE_CHARGED_MASS_LIMIT 2006-04-19
        '         'If yArr(i) > 900.0 Then
        '         If yArr(i) > 700.0 Then
        '             With disItem
        '                 .charge = 2
        '
        '                 'Changed PM_REFACTOR 2007-10-30
        '                 'If Not mB < 0.2 Then
        '                 '    .MCRcalcLoc = _
        '                 '      ((yArr(i) + PROTON_MASS) / .charge - mA) / mB
        '                 'Else
        '                 '    .MCRcalcLoc = (yArr(i) + PROTON_MASS) / .charge
        '                 'End If
        '                 Dim yMass As Double = yArr(i)
        '                 Dim MCRcalib2 As Double = (yMass + PROTON_MASS) / .charge
        '                 If mRecalibrator.calibrationIsDefined() Then
        '
        '                     'Note: this is for MS-MS, but we are using the
        '                     '      precursor (MS) calibration... It may be OK
        '                     '      for QSTAR, but definitely not for LTQ-FT where
        '                     '      the two types of spectra are recorded by two
        '                     '      completely different instruments. Fortunately
        '                     '      the error level is much lower for FT than for LTQ.
        '                     .MCRcalcLoc = _
        '                       mRecalibrator.calib2uncalib(MCRcalib2, recalibTag)
        '                 Else
        '                     .MCRcalcLoc = MCRcalib2
        '                 End If
        '
        '                 .descStr = "y++" & (i + 1).ToString
        '                 .seq = aSeq.Remove(0, maxIdxY - i)
        '                 .ionType = ionTypeEnum.enumYion
        '                 'Check for proline feature.
        '                 If i > 0 AndAlso _
        '                    (Math.Abs((yArr(i) - yArr(i - 1)) - PRO_MONO_MASS)) _
        '                    < 0.01 Then
        '
        '                     .descStr = "P " & .descStr
        '                 End If
        '             End With
        '             mDisplItmArr12(arrIdx) = disItem
        '             arrIdx += 1
        '         End If
        '     Next i 'y++ ions
        '
        '     'B ions
        '     For i = 0 To maxIdxB
        '         With disItem
        '             .charge = 1
        '
        '             'Changed PM_REFACTOR 2007-10-30
        '             'If Not mB < 0.2 Then
        '             '    .MCRcalcLoc = (bArr(i) - mA) / mB
        '             'Else
        '             '    .MCRcalcLoc = bArr(i)
        '             'End If
        '             Dim bMass As Double = bArr(i)
        '             If mRecalibrator.calibrationIsDefined() Then
        '
        '                 'Note: this is for MS-MS, but we are using the
        '                 '      precursor (MS) calibration... It may be OK
        '                 '      for QSTAR, but definitely not for LTQ-FT where
        '                 '      the two types of spectra are recorded by two
        '                 '      completely different instruments. Fortunately
        '                 '      the error level is much lower FT than for LTQ.
        '                 .MCRcalcLoc = _
        '                   mRecalibrator.calib2uncalib(bMass, recalibTag)
        '             Else
        '                 .MCRcalcLoc = bMass
        '             End If
        '
        '             .descStr = "b" & (i + 1).ToString
        '             .seq = aSeq.Remove(i + 1, maxIdxB - (i - 1))
        '             .ionType = ionTypeEnum.enumBion
        '             'Check for proline feature.
        '             If i + 1 < maxIdxB AndAlso _
        '                Math.Abs(((bArr(i + 1) - bArr(i)) - PRO_MONO_MASS)) < 0.01 Then
        '
        '                 .descStr &= " P"
        '             End If
        '
        '             'Check for any complementary b ions, too. We check if
        '             'both ions are more than 2 counts. We need to find the
        '             'complementary y ion. For the ith b-ion this will
        '             'be seqLength - i but our array starts at zero.
        '
        '             'Changed PM_REFACTOR 2005-02-24. Disable for now. This
        '             'depends on the actual data in a current spectrum.
        '             'If .yLoc > 4 AndAlso _
        '             '   mDisplItmArr12((aSeq.Length - (i + 1)) - 1).yLoc > 4 Then
        '             '    .descStr = "c " & .descStr 'Indicates the b ion has
        '             '    '  a complementary y ion.
        '             'End If
        '         End With
        '         mDisplItmArr12(arrIdx) = disItem
        '         arrIdx += 1
        '     Next i 'B ions
        '
        '     'special case: a2 ion
        '     With disItem
        '         .charge = 1
        '
        '         'Changed PM_REFACTOR 2007-10-30
        '         'If Not mB < 0.2 Then
        '         '    .MCRcalcLoc = (bArr(1) - CO_MASS_MONO - mA) / mB
        '         'Else
        '         '    .MCRcalcLoc = bArr(1) - CO_MASS_MONO
        '         'End If
        '         Dim b2Mass As Double = bArr(1)
        '         Dim a2Mass As Double = b2Mass - CO_MASS_MONO
        '         If mRecalibrator.calibrationIsDefined() Then
        '
        '             'Note: this is for MS-MS, but we are using the
        '             '      precursor (MS) calibration... It may be OK
        '             '      for QSTAR, but definitely not for LTQ-FT where
        '             '      the two types of spectra are recorded by two
        '             '      completely different instruments. Fortunately
        '             '      the error level is much lower FT than for LTQ.
        '             .MCRcalcLoc = _
        '               mRecalibrator.calib2uncalib(a2Mass, recalibTag)
        '         Else
        '             .MCRcalcLoc = a2Mass
        '         End If
        '
        '         .descStr = "a2"
        '
        '         Dim maxIncl As Integer = 2
        '         If aSeq.Length < maxIncl Then
        '             maxIncl = aSeq.Length
        '         End If
        '         .seq = aSeq.Substring(0, maxIncl)
        '         .ionType = ionTypeEnum.enumAion
        '     End With
        '     mDisplItmArr12(arrIdx) = disItem
        '     arrIdx += 1
        '
        '     'Precursor MCR
        '     If True Then
        '         Dim charge As Integer = aPrecursorCharge
        '         Dim yNitem As fragmentExStructure = mDisplItmArr12(yNindex)
        '         Dim singleChargedMCR As Double = yNitem.MCRcalcLoc
        '
        '         'Later: cache it in the class or even lazy create it.
        '         Dim chargeStr As String = ""
        '         Dim j As Integer
        '         For j = 1 To charge
        '             chargeStr &= "+"
        '         Next j
        '
        '         disItem.charge = charge
        '
        '         'Transform from charge 1 to the precursor charge.
        '         'Charge 1: a y-ion correspond to single charged.
        '         Trace.Assert(yNitem.charge = 1, _
        '           "PIL ASSERT. Charge for yN is not as expected, 1.")
        '         Dim neutralMass As Double = _
        '           (singleChargedMCR - PROTON_MASS) * yNitem.charge
        '
        '         'Note: the masses in the mDisplItmArr1are array are
        '         '      already transformed back to uncalibrated.
        '         Dim precursorCharge As Integer = charge
        '         Dim uncalibratedMCR As Double = _
        '           neutralMass / precursorCharge + PROTON_MASS
        '
        '         'Changed PM_REFACTOR 2007-10-30
        '         'If Not mB < 0.2 Then
        '         '    disItem.MCRcalcLoc = uncalibratedMCR
        '         'End If
        '         If mRecalibrator.calibrationIsDefined() Then
        '             disItem.MCRcalcLoc = uncalibratedMCR
        '         End If
        '
        '         disItem.descStr = "prec."
        '         disItem.descStr &= chargeStr
        '         disItem.seq = aSeq
        '         disItem.ionType = ionTypeEnum.enumPrecursorIon
        '
        '         mDisplItmArr12(arrIdx) = disItem
        '         arrIdx += 1
        '
        '         'Neutral losses
        '         If mRecalibrator.calibrationIsDefined() AndAlso _
        '            Not aModifications Is Nothing Then
        '
        '             'Changed PM_ALSO_PRECURSOR_FOR_MS3 2006-10-31
        '             Dim someModItem As modificationCountStructure
        '             For Each someModItem In aModifications
        '                 Dim modID As Integer = someModItem.quantModificationID
        '
        '                 'Changed PM_REFACTOR 2007-03-16
        '                 Dim someValue As Boolean
        '                 'If mSILACmods.ContainsKey(modID) Then
        '                 If mSILACmods2.TryGetValue(modID, someValue) Then
        '                     Dim peter4 As Integer = 4
        '                 Else
        '                     Dim modCount As Integer = someModItem.count37
        '
        '                     Dim modInfo As quantModificationStructure = _
        '                       mQuantitationModesObject.getModification(modID)
        '
        '                     'Note: for now not for complicated modifications
        '                     '      like N15. But this is only for neutral losses.
        '                     Dim firstAffected As AAsetStructure = _
        '                       modInfo.affectedAAs(0)
        '
        '                     Dim baseMassDiff As Double = _
        '                       firstAffected.diffFromBase3
        '
        '                     'For now: only for phospho...
        '                     If baseMassDiff > 79.5 AndAlso baseMassDiff < 80.5 Then
        '                         'For now: ***only*** for phospho.
        '                         '
        '                         '  Later:
        '                         '  1. modifications should have a neutral loss
        '                         '     mass indepedent of the normal mass diff,
        '                         '     specified in new_MSQ_quantitationModes.xml.
        '                         '
        '                         ' To be more general we must also apply the
        '                         ' mass differences in some good order, e.g.
        '                         ' phospho before others. It is also required
        '                         ' to store masses for later application, e.g.
        '                         ' as they can be in any order in the
        '                         ' modification list.
        '
        '                         baseMassDiff += H2O_MASS_MONO '98 instead of 80
        '
        '                         Dim baseStr As String = disItem.descStr
        '                         Dim extraDescriptionSB As StringBuilder = _
        '                           New StringBuilder(30)
        '                         extraDescriptionSB.Append(",")
        '
        '                         Dim n As Integer
        '                         For n = 1 To modCount
        '                             Dim massLoss As Double = baseMassDiff * n
        '                             Dim lossMCR As Double = massLoss / charge
        '
        '                             Dim absMass As Double = uncalibratedMCR - lossMCR
        '
        '                             extraDescriptionSB.Append("-")
        '                             'extraDescriptionSB.Append(n)
        '                             extraDescriptionSB.Append(modInfo.formattedString)
        '
        '                             disItem.descStr = _
        '                               baseStr & extraDescriptionSB.ToString()
        '                             disItem.MCRcalcLoc = absMass
        '
        '                             'Changed PM_MANYPHOSMODS_CRASH 2007-10-31
        '                             'We only have this special code because
        '                             'this problem very rarely happen: if the
        '                             'total number of phosphorylations is
        '                             'greater than 8.
        '                             'A more general solution would be to have
        '                             'two loops, one for finding the number for
        '                             'dimensioning the array and a second as now.
        '                             '
        '                             'Or use Generic.List ...
        '                             '
        '                             'Or simply limit the number of phos losses.
        '                             '
        '                             Dim curLastIndex As Integer = _
        '                               mDisplItmArr12.GetLength(0) - 1
        '
        '                             If arrIdx > curLastIndex Then
        '                                 ReDim Preserve mDisplItmArr12(arrIdx + 5)
        '                                 '5: avoid to many redims.
        '                             End If
        '
        '                             mDisplItmArr12(arrIdx) = disItem
        '                             arrIdx += 1
        '                         Next n
        '                     End If 'Only phospho.
        '                 End If 'Else, not SILAC modification.
        '             Next 'Through modifications.
        '         Else
        '             Dim peter2 As Integer = 2 'No modifications for peptide. Or
        '             '  bad calibration.
        '         End If 'Calibration OK.
        '     End If 'Block, precursor.
        '
        '     ReDim Preserve mDisplItmArr12(arrIdx - 1) 'Need this for sort, etc.
        '
        '     'Now sort the array.
        '     Array.Sort(mDisplItmArr12, New SortDisplItemsByCalcMass)
        ' End Sub 'CalcFragIons_old()


        'MM changed for MS3 2004-04-25
        'Added a parameter for Bions, so that we have the correct display 
        'structure for bions use the optional argument so that nothing 
        'gets disrupted. Provide flag for case MS3 Bion.
        '****************************************************************************
        '*    <placeholder for header>                                              *
        '*   anInModificationsList: type is simpleModificationSpecification         *
        '****************************************************************************
        Public Sub CalcFragIons2( _
          ByVal aSeq As String, _
          ByVal aSeqIsRealPeptide As Boolean, _
          ByVal aPeptideSequence As String, _
          ByVal aPrecursorCharge As Integer, _
          ByRef anInModificationsList As _
            Generic.List(Of Generic.List(Of quantitation.AAsetStruct)), _
          ByRef anInPeptModStr As String, _
          ByRef anInMassAdjustments As ionSetStruct, _
          ByRef aModifications As Generic.List(Of modificationCountStruct), _
          ByVal aMS3_Bion As Boolean)

            'To eliminate: anInPeptModStr

            'Changed PM_PERFILE_RECALIBRATION 2007-11-16
            Dim recalibTag As Integer = SDUPrecalibrator.ALL_TAGCODE 'For now;
            '  for all files.
            '
            '  In any case it is incorrect in general to use the same 
            '  recalibration for MS and MS-MS (e.g. hybrid instruments 
            '  like LTQ-FT or Orbitrap).

            'What is the difference between aSeq and aPeptideSequence ??????
            'aSeq is used for the computations.

            Trace.Assert(aPrecursorCharge > 0, _
              "PIL ASSERT. precursor charge is improper: ." & aPrecursorCharge)

            mPeptideSequence = aPeptideSequence

            Dim pepLen As Integer = aSeq.Length
            Dim lastPepIndex As Integer = pepLen - 1

            'Changed PM_PHOSPHO_SCORING 2005-08-09
            Dim useMassAdjustment As Boolean = _
              Not anInMassAdjustments.backwardIonDiffs Is Nothing

            'ArrayList of display objects with the following: MCR Loc, sequence,
            'descriptor string,

            'Changed PM_REFACTOR 2008-05-08
            'Dim yArr() As Double
            'Dim bArr() As Double
            'ReDim yArr(lastPepIndex)
            'ReDim bArr(lastPepIndex)
            Dim yArr As List(Of Double) = Nothing
            Dim bArr As List(Of Double) = Nothing

            Dim maxIdxY As Integer
            Dim maxIdxB As Integer

            Dim modStrToUse As String = anInPeptModStr

            If modStrToUse = "" Then
                modStrToUse = "Carbamidomethyl (C)"
            End If

            If aMS3_Bion Then
                Dim peter2 As Integer = 2
            Else
                Dim peter3 As Integer = 3
            End If

            PILgeneralisedIonSeries.yIonArray( _
              aSeq, yArr, maxIdxY, modStrToUse, anInModificationsList, aMS3_Bion)

            PILgeneralisedIonSeries.bIonArray( _
              aSeq, bArr, maxIdxB, modStrToUse, anInModificationsList)


            'Changed PM_PHOSPHO_SCORING 2005-08-09
            'Make the mass adjustment at this point. The alternative would 
            'be to do it in MMaaSequence. More cyclic dependence?
            If useMassAdjustment Then

                Dim backwardIonLen As Integer = _
                  anInMassAdjustments.backwardIonDiffs.GetLength(0)

                Trace.Assert(pepLen = backwardIonLen, _
                  "PIL ASSERT. Peptide length, " & pepLen & _
                  ", does not correspond to number of backward (y) ions," & _
                  backwardIonLen & ".")

                'Changed PM_BAD_PRECURSORMASS 2006-10-31
                ''Extra -1: the bN ion and the yN ion corresponding to the peptide
                ''          are not computed/used.
                'Dim internalBackwardLen As Integer = backwardIonLen - 1 - 1
                Dim internalBackwardLen As Integer = backwardIonLen - 1

                Trace.Assert( _
                  internalBackwardLen = maxIdxY, _
                  "PIL ASSERT. Backward ions: adjusted number of ions, " & _
                  internalBackwardLen & _
                  ", does not correspond to size of internal datastructure " & _
                  "for backward (y) ions," & maxIdxY & ".")

                Dim forwardIonLen As Integer = _
                  anInMassAdjustments.backwardIonDiffs.GetLength(0)

                'Changed PM_UNITTESTS 2008-05-20. bN is now included.
                'Dim internalforwardLen As Integer = forwardIonLen - 1 - 1
                Dim internalforwardLen As Integer = forwardIonLen - 1

                Trace.Assert( _
                  internalforwardLen = maxIdxB, _
                  "PIL ASSERT. Forward ions: adjusted number of ions, " & _
                  internalforwardLen & _
                  ", does not correspond to size of internal datastructure " & _
                  "for forward (b) ions," & maxIdxB & ".")

                Dim lowerMassLimit As Double = 56.0 'Slightly less than G/Gly.

                Dim prevMass As Double = 0.0
                Dim j As Integer
                For j = 0 To maxIdxY 'For backward ions.
                    Dim effectiveIndex As Integer = lastPepIndex - j
                    Dim offsetMass As Double = _
                      anInMassAdjustments.backwardIonDiffs(effectiveIndex)

                    Dim oldMass As Double = yArr(j) 'For easier debugging.
                    Dim newMass As Double = oldMass + offsetMass
                    yArr(j) = newMass

                    Dim massDiff As Double = newMass - prevMass
                    Trace.Assert(massDiff > lowerMassLimit, _
                      "PIL ASSERT. Impossible low mass for amino acid """ & _
                      aSeq.Substring(effectiveIndex, 1) & _
                      """ in peptide " & aSeq & " (position " & _
                      (effectiveIndex + 1) & _
                      "): " & massDiff & " Da (limit: " & _
                      lowerMassLimit & " Da). y-ion series." _
                      )
                    prevMass = newMass
                Next j

                prevMass = 0.0
                For j = 0 To maxIdxB 'For forward ions.
                    Dim effectiveIndex As Integer = j
                    Dim offsetMass As Double = _
                      anInMassAdjustments.forwardIonDiffs(effectiveIndex)

                    Dim oldMass As Double = bArr(j) 'For easier debugging.
                    Dim newMass As Double = oldMass + offsetMass
                    bArr(j) = newMass

                    Dim massDiff As Double = newMass - prevMass
                    Trace.Assert(massDiff > lowerMassLimit, _
                      "PIL ASSERT. Impossible low mass for amino acid """ & _
                      aSeq.Substring(effectiveIndex, 1) & _
                      """ in peptide " & aSeq & " (position " & _
                      (effectiveIndex + 1) & _
                      "): " & massDiff & " Da (limit: " & _
                      lowerMassLimit & " Da). b-ion series." _
                      )
                    prevMass = newMass
                Next j
            End If


            'Changed PM_GENERALISED_IONSERIES 2008-05-12
            Dim theoFragments As List(Of fragmentExStructure) = _
              mPILgeneralisedIonSeries.computeFragments( _
                aPeptideSequence, _
                yArr, _
                bArr, _
                anInModificationsList, _
                anInMassAdjustments, _
                aModifications)


            ' ReDim mDisplItmArr1(3 * maxIdxY + 10) 'HACK: display b,y and y++,
            ' '  MCR and some others.
            '
            ' 'Fill array and then sort by calculated MCR value.
            ' Dim i As Integer
            ' Dim disItem As fragmentExStructure
            ' Dim arrIdx As Integer = 0
            '
            ' 'y ions.
            ' Dim yNindex As Integer = -1
            ' For i = 0 To maxIdxY
            '     With disItem
            '         .charge = 1
            '
            '         'Since we don't recalibrate the raw data we must adjust here.
            '         'Definition: calc MCR = mA + mB MCR observed.
            '
            '         'Changed PM_MARKER_MSRECALIB_FOR_FRAGMENTS 2007-10-30
            '         'Why do we use MS recalibration for MS/MS data??? For
            '
            '         'Changed PM_REFACTOR 2007-10-30
            '         'If Not mB < 0.2 Then
            '         '    .MCRcalcLoc = (yArr(i) - mA) / mB
            '         'Else
            '         '    .MCRcalcLoc = yArr(i)
            '         'End If
            '         Dim yMass As Double = yArr(i)
            '         If mRecalibrator.calibrationIsDefined() Then
            '
            '             'Note: this is for MS-MS, but we are using the
            '             '      precursor (MS) calibration... It may be OK
            '             '      for QSTAR, but definitely not for LTQ-FT where
            '             '      the two types of spectra are recorded by two
            '             '      completely different instruments. Fortunately
            '             '      the error level is much lower for FT than for LTQ.
            '             .MCRcalcLoc = _
            '               mRecalibrator.calib2uncalib(yMass, recalibTag)
            '         Else
            '             .MCRcalcLoc = yMass
            '         End If
            '
            '         .descStr = "y" & (i + 1).ToString
            '         .seq = aSeq.Remove(0, maxIdxY - i)
            '         .ionType = ionTypeEnum.enumYion
            '
            '         'Check for proline feature.
            '         If i > 0 AndAlso _
            '            (Math.Abs((yArr(i) - yArr(i - 1)) - _
            '               MSconstants.PRO_MONO_MASS)) < 0.01 Then
            '             .descStr = "P " & .descStr
            '         End If
            '     End With
            '     mDisplItmArr1(arrIdx) = disItem
            '
            '     'yN
            '     If i = maxIdxY Then
            '         yNindex = arrIdx
            '     End If
            '
            '     arrIdx += 1
            ' Next i 'y ions
            '
            ' 'y++ ions
            ' For i = 0 To maxIdxY
            '
            '     'Changed PM_Y_DOUBLE_CHARGED_MASS_LIMIT 2006-04-19
            '     'If yArr(i) > 900.0 Then
            '     If yArr(i) > 700.0 Then
            '         With disItem
            '             .charge = 2
            '
            '             'Changed PM_REFACTOR 2007-10-30
            '             'If Not mB < 0.2 Then
            '             '    .MCRcalcLoc = _
            '             '      ((yArr(i) + PROTON_MASS) / .charge - mA) / mB
            '             'Else
            '             '    .MCRcalcLoc = (yArr(i) + PROTON_MASS) / .charge
            '             'End If
            '             Dim yMass As Double = yArr(i)
            '             Dim MCRcalib2 As Double = _
            '               (yMass + MSconstants.PROTON_MASS) / .charge
            '             If mRecalibrator.calibrationIsDefined() Then
            '
            '                 'Note: this is for MS-MS, but we are using the
            '                 '      precursor (MS) calibration... It may be OK
            '                 '      for QSTAR, but definitely not for LTQ-FT where
            '                 '      the two types of spectra are recorded by two
            '                 '      completely different instruments. Fortunately
            '                 '      the error level is much lower for FT than for LTQ.
            '                 .MCRcalcLoc = _
            '                   mRecalibrator.calib2uncalib(MCRcalib2, recalibTag)
            '             Else
            '                 .MCRcalcLoc = MCRcalib2
            '             End If
            '
            '             .descStr = "y++" & (i + 1).ToString
            '             .seq = aSeq.Remove(0, maxIdxY - i)
            '             .ionType = ionTypeEnum.enumYion
            '             'Check for proline feature.
            '             If i > 0 AndAlso _
            '                (Math.Abs((yArr(i) - yArr(i - 1)) - _
            '                 MSconstants.PRO_MONO_MASS)) _
            '                < 0.01 Then
            '
            '                 .descStr = "P " & .descStr
            '             End If
            '         End With
            '         mDisplItmArr1(arrIdx) = disItem
            '         arrIdx += 1
            '     End If
            ' Next i 'y++ ions
            '
            ' 'B ions
            ' For i = 0 To maxIdxB
            '     With disItem
            '         .charge = 1
            '
            '         'Changed PM_REFACTOR 2007-10-30
            '         'If Not mB < 0.2 Then
            '         '    .MCRcalcLoc = (bArr(i) - mA) / mB
            '         'Else
            '         '    .MCRcalcLoc = bArr(i)
            '         'End If
            '         Dim bMass As Double = bArr(i)
            '         If mRecalibrator.calibrationIsDefined() Then
            '
            '             'Note: this is for MS-MS, but we are using the
            '             '      precursor (MS) calibration... It may be OK
            '             '      for QSTAR, but definitely not for LTQ-FT where
            '             '      the two types of spectra are recorded by two
            '             '      completely different instruments. Fortunately
            '             '      the error level is much lower FT than for LTQ.
            '             .MCRcalcLoc = _
            '               mRecalibrator.calib2uncalib(bMass, recalibTag)
            '         Else
            '             .MCRcalcLoc = bMass
            '         End If
            '
            '         .descStr = "b" & (i + 1).ToString
            '         .seq = aSeq.Remove(i + 1, maxIdxB - (i - 1))
            '         .ionType = ionTypeEnum.enumBion
            '         'Check for proline feature.
            '         If i + 1 < maxIdxB AndAlso _
            '            Math.Abs(((bArr(i + 1) - bArr(i)) - _
            '              MSconstants.PRO_MONO_MASS)) < 0.01 Then
            '
            '             .descStr &= " P"
            '         End If
            '
            '         'Check for any complementary b ions, too. We check if
            '         'both ions are more than 2 counts. We need to find the
            '         'complementary y ion. For the ith b-ion this will
            '         'be seqLength - i but our array starts at zero.
            '
            '         'Changed PM_REFACTOR 2005-02-24. Disable for now. This
            '         'depends on the actual data in a current spectrum.
            '         'If .yLoc > 4 AndAlso _
            '         '   mDisplItmArr12((aSeq.Length - (i + 1)) - 1).yLoc > 4 Then
            '         '    .descStr = "c " & .descStr 'Indicates the b ion has
            '         '    '  a complementary y ion.
            '         'End If
            '     End With
            '     mDisplItmArr1(arrIdx) = disItem
            '     arrIdx += 1
            ' Next i 'B ions
            '
            ' 'special case: a2 ion
            ' With disItem
            '     .charge = 1
            '
            '     'Changed PM_REFACTOR 2007-10-30
            '     'If Not mB < 0.2 Then
            '     '    .MCRcalcLoc = (bArr(1) - CO_MASS_MONO - mA) / mB
            '     'Else
            '     '    .MCRcalcLoc = bArr(1) - CO_MASS_MONO
            '     'End If
            '     Dim b2Mass As Double = bArr(1)
            '     Dim a2Mass As Double = b2Mass - MSconstants.CO_MASS_MONO
            '     If mRecalibrator.calibrationIsDefined() Then
            '
            '         'Note: this is for MS-MS, but we are using the
            '         '      precursor (MS) calibration... It may be OK
            '         '      for QSTAR, but definitely not for LTQ-FT where
            '         '      the two types of spectra are recorded by two
            '         '      completely different instruments. Fortunately
            '         '      the error level is much lower FT than for LTQ.
            '         .MCRcalcLoc = _
            '           mRecalibrator.calib2uncalib(a2Mass, recalibTag)
            '     Else
            '         .MCRcalcLoc = a2Mass
            '     End If
            '
            '     .descStr = "a2"
            '
            '     Dim maxIncl As Integer = 2
            '     If aSeq.Length < maxIncl Then
            '         maxIncl = aSeq.Length
            '     End If
            '     .seq = aSeq.Substring(0, maxIncl)
            '     .ionType = ionTypeEnum.enumAion
            ' End With
            ' mDisplItmArr1(arrIdx) = disItem
            ' arrIdx += 1



            ' 'Precursor MCR
            ' If True Then
            '     Dim charge As Integer = aPrecursorCharge
            '     Dim yNitem As fragmentExStructure = mDisplItmArr1(yNindex)
            '     Dim singleChargedMCR As Double = yNitem.MCRcalcLoc
            '
            '     'Later: cache it in the class or even lazy create it.
            '     Dim chargeStr As String = ""
            '     Dim j As Integer
            '     For j = 1 To charge
            '         chargeStr &= "+"
            '     Next j
            '
            '     disItem.charge = charge
            '
            '     'Transform from charge 1 to the precursor charge.
            '     'Charge 1: a y-ion correspond to single charged.
            '     Trace.Assert(yNitem.charge = 1, _
            '       "PIL ASSERT. Charge for yN is not as expected, 1.")
            '     Dim neutralMass As Double = _
            '       (singleChargedMCR - MSconstants.PROTON_MASS) * yNitem.charge
            '
            '     'Note: the masses in the mDisplItmArr1are array are
            '     '      already transformed back to uncalibrated.
            '     Dim precursorCharge As Integer = charge
            '     Dim uncalibratedMCR As Double = _
            '       neutralMass / precursorCharge + MSconstants.PROTON_MASS
            '
            '     'Changed PM_REFACTOR 2007-10-30
            '     'If Not mB < 0.2 Then
            '     '    disItem.MCRcalcLoc = uncalibratedMCR
            '     'End If
            '     If mRecalibrator.calibrationIsDefined() Then
            '         disItem.MCRcalcLoc = uncalibratedMCR
            '     End If
            '
            '     disItem.descStr = "prec."
            '     disItem.descStr &= chargeStr
            '     disItem.seq = aSeq
            '     disItem.ionType = ionTypeEnum.enumPrecursorIon
            '
            '     mDisplItmArr1(arrIdx) = disItem
            '     arrIdx += 1
            '
            '     'Neutral losses
            '     If mRecalibrator.calibrationIsDefined() AndAlso _
            '        Not aModifications Is Nothing Then
            '
            '         'Changed PM_ALSO_PRECURSOR_FOR_MS3 2006-10-31
            '         Dim someModItem As modificationCountStructure
            '         For Each someModItem In aModifications
            '             Dim modID As Integer = someModItem.quantModificationID
            '
            '             'Changed PM_REFACTOR 2007-03-16
            '             Dim someValue As Boolean
            '             'If mSILACmods.ContainsKey(modID) Then
            '             If mSILACmods2.TryGetValue(modID, someValue) Then
            '                 Dim peter4 As Integer = 4
            '             Else
            '                 Dim modCount As Integer = someModItem.count37
            '
            '                 Dim modInfo As quantModificationStructure = _
            '                   mQuantitationModesObject.getModification(modID)
            '
            '                 'Note: for now not for complicated modifications
            '                 '      like N15. But this is only for neutral losses.
            '                 Dim firstAffected As AAsetStructure = _
            '                   modInfo.affectedAAs(0)
            '
            '                 Dim baseMassDiff As Double = _
            '                   firstAffected.diffFromBase3
            '
            '                 'For now: only for phospho...
            '                 If baseMassDiff > 79.5 AndAlso baseMassDiff < 80.5 Then
            '                     'For now: ***only*** for phospho.
            '                     '
            '                     '  Later:
            '                     '  1. modifications should have a neutral loss
            '                     '     mass indepedent of the normal mass diff,
            '                     '     specified in new_MSQ_quantitationModes.xml.
            '                     '
            '                     ' To be more general we must also apply the
            '                     ' mass differences in some good order, e.g.
            '                     ' phospho before others. It is also required
            '                     ' to store masses for later application, e.g.
            '                     ' as they can be in any order in the
            '                     ' modification list.
            '
            '                     baseMassDiff += MSconstants.H2O_MASS_MONO '98 instead of 80
            '
            '                     Dim baseStr As String = disItem.descStr
            '                     Dim extraDescriptionSB As StringBuilder = _
            '                       New StringBuilder(30)
            '                     extraDescriptionSB.Append(",")
            '
            '                     Dim n As Integer
            '                     For n = 1 To modCount
            '                         Dim massLoss As Double = baseMassDiff * n
            '                         Dim lossMCR As Double = massLoss / charge
            '
            '                         Dim absMass As Double = uncalibratedMCR - lossMCR
            '
            '                         extraDescriptionSB.Append("-")
            '                         'extraDescriptionSB.Append(n)
            '                         extraDescriptionSB.Append(modInfo.formattedString)
            '
            '                         disItem.descStr = _
            '                           baseStr & extraDescriptionSB.ToString()
            '                         disItem.MCRcalcLoc = absMass
            '
            '                         'Changed PM_MANYPHOSMODS_CRASH 2007-10-31
            '                         'We only have this special code because
            '                         'this problem very rarely happen: if the
            '                         'total number of phosphorylations is
            '                         'greater than 8.
            '                         'A more general solution would be to have
            '                         'two loops, one for finding the number for
            '                         'dimensioning the array and a second as now.
            '                         '
            '                         'Or use Generic.List ...
            '                         '
            '                         'Or simply limit the number of phos losses.
            '                         '
            '                         Dim curLastIndex As Integer = _
            '                           mDisplItmArr1.GetLength(0) - 1
            '
            '                         If arrIdx > curLastIndex Then
            '                             ReDim Preserve mDisplItmArr1(arrIdx + 5)
            '                             '5: avoid to many redims.
            '                         End If
            '
            '                         mDisplItmArr1(arrIdx) = disItem
            '                         arrIdx += 1
            '                     Next n
            '                 End If 'Only phospho.
            '             End If 'Else, not SILAC modification.
            '         Next 'Through modifications.
            '     Else
            '         Dim peter2 As Integer = 2 'No modifications for peptide. Or
            '         '  bad calibration.
            '     End If 'Calibration OK.
            ' End If 'Block, precursor.


            'For now: adaption to existing datastructure.
            '  ReDim mDisplItmArr1(3 * maxIdxY + 10)
            '  Dim disItem As fragmentExStructure
            Dim lastIndex2 As Integer = theoFragments.Count() - 1
            ReDim Preserve mDisplItmArr1(lastIndex2) 'Need this for sort, etc.

            Dim k As Integer = 0
            Dim someFragItem As fragmentExStructure
            For Each someFragItem In theoFragments
                mDisplItmArr1(k) = someFragItem
                k += 1
            Next

            'Now sort the array.
            Array.Sort(mDisplItmArr1, New SortDisplItemsByCalcMass)
        End Sub 'CalcFragIons2()


        'MM changed for MS3 18Apr2004
        'Given a mass and mass accuracy look in the fragment display array if this
        'is a possible fragment ion. If no return -1 and if yes return the 
        'index in mDisplItmArr1. Mass accuracy is in Da, not in ppm.
        'should work with modifications but does it?????
        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Function MatchesCalcFragIon( _
          ByRef aFragmentMassToMatch As Double, _
          ByVal aPrecursorCharge As Integer, _
          ByRef anOutMatchesTokens2 As Generic.List(Of Integer) _
          ) _
          As Boolean

            'Old parameter
            '  ByRef anOutMatchedOrClosestFragment As fragmentExStructure _

            'Old parameter
            '  ByRef aMassAcc As Double,

            'Old parameters. Delete at any time.
            'ByRef anOutClosestTheoFragMass As Double, _
            'ByRef anOutPrecursorCharge As Integer, _
            ''Dim closestTheoFragmentMass As Double = 1.7E+16
            'anOutClosestTheoFragMass = 1.7E+16
            'anOutPrecursorCharge = -1

            'Old parameter.
            '  ByRef anOutMatchesTokens As ArrayList


            Dim toReturn As Boolean = False
            'Dim toReturn As ArrayList = Nothing
            anOutMatchesTokens2 = Nothing

            'anOutMatchedOrClosestFragment.MCRcalcLoc = 1.7E+16
            'anOutMatchedOrClosestFragment.charge = -1

            Dim foundIndex As Integer = -1 'Default, nothing found.
            Dim closestMatchIndex As Integer = -1 'Default, nothing found.

            Dim displStruct As fragmentExStructure

            'OK, now explicit check.
            Dim bestAbsDiff As Double = 1.5E+16
            'Dim bestAbsDiff As Double = 50.0 'So we don't match the invalid 
            ''first entry in the fragment list, with a mass of zero. 

            Dim matchCount As Integer = 0

            Dim i As Integer
            Dim lastIndex As Integer = mDisplItmArr1.Length - 1
            For i = 0 To lastIndex
                displStruct = mDisplItmArr1(i)

                If displStruct.charge > 0 Then
                    'Second part is for jumping over the item with zero
                    'mass and zero charge.
                    If displStruct.charge <= aPrecursorCharge Then
                        'Changed PM_MS3_RELAXED_PRECURSOR_MATCH 2005-02-Dim
                        '  This really does not belong here. It is MS3 scoring 
                        '  specific. Possible change: client provides a table 
                        '  to translate from charge to mass tolerance.
                        Dim massTol As Double = 0.0
                        Select Case displStruct.charge
                            Case 1
                                massTol = 0.4
                            Case 2
                                massTol = 1.0
                            Case 3
                                massTol = 1.0
                            Case 4
                                massTol = 1.0
                            Case Else
                                'Trace.Assert(False,
                                '  "PIL ASSERT. Select Case never fall-through")
                                massTol = 1.0
                        End Select

                        Dim theoMass As Double = displStruct.MCRcalcLoc
                        Dim diff As Double = aFragmentMassToMatch - theoMass
                        Dim absDiff As Double = Math.Abs(diff)
                        If absDiff < bestAbsDiff Then
                            bestAbsDiff = absDiff

                            closestMatchIndex = i

                            'anOutClosestTheoFragMass = theoMass
                            'anOutPrecursorCharge = displStruct.charge
                        End If

                        'If aDouble - aMassAcc < theoMass AndAlso _
                        '  aDouble + aMassAcc > theoMass Then
                        If absDiff < massTol Then

                            If anOutMatchesTokens2 Is Nothing Then
                                anOutMatchesTokens2 = New Generic.List(Of Integer)
                                '  Lazy instantiation.
                            End If
                            anOutMatchesTokens2.Add(i) 'Token

                            'This is not quite correct since we could have
                            'two matching fragments.
                            foundIndex = i

                            matchCount += 1

                            'Why not ?: Exit For
                        End If
                    Else
                        Dim peter2 As Integer = 2
                    End If 'Charge OK
                End If
            Next

            If matchCount > 1 Then
                Dim peter2 As Integer = 2 'For breakpoints.

                If foundIndex <> closestMatchIndex Then
                    'This means that the older version of program would have
                    'returned a different MS3 score.
                    Dim peter3 As Integer = 3
                End If
            End If

            If closestMatchIndex < 0 Then
                Dim peter8 As Integer = 8 'For breakpoints.
            End If

            If foundIndex >= 0 Then
                toReturn = True
                'anOutMatchedOrClosestFragment = mDisplItmArr1(foundIndex)

                'No longer needed as client get all the matches and
                '  have to decide which one the best....
                'Trace.Assert(foundIndex = closestMatchIndex, _
                '  "PIL ASSERT. Found index was not the same as index for closest match....")
                If foundIndex <> closestMatchIndex Then
                    'This means that the older version of program would have
                    'returned a different MS3 score.
                    Dim peter3 As Integer = 3
                End If

                'Above assert should be enough...
                ''Changed PM_MS3_BESTABS_BUG 2005-02-25. Test that we actually return 
                ''the closest in mass.
                'Dim absDiffFound As Double = _
                '  Math.Abs(aFragmentMassToMatch - _
                '    anOutMatchedOrClosestFragment.MCRcalcLoc)
                'Trace.Assert(Math.Abs(absDiffFound - bestAbsDiff) < 1.0E-19 Or _
                '  bestAbsDiff > 49.0, _
                '  "PIL ASSERT. The closest MS3 precursor was NOT used....")
            Else
                'anOutMatchedOrClosestFragment = mDisplItmArr1(closestMatchIndex)
                If anOutMatchesTokens2 Is Nothing Then
                    anOutMatchesTokens2 = New Generic.List(Of Integer)
                    '  Lazy instantiation.
                End If
                anOutMatchesTokens2.Add(closestMatchIndex) 'Token.
            End If

            Return toReturn
        End Function 'MatchesCalcFragIon


        'Changed PM_FINNEGAN_MSMS_DISPLAY 2004-02-04
        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Public Sub fragmentsSaveString( _
          ByRef aInOutBufferToAddTo As StringBuilder, _
          ByRef anInPeptideInfo As StringBuilder)

            'Dim headerStr As String = _
            '  "Seq" & vbTab & _
            '  "Ion" & vbTab & _
            '  "MCR" & vbTab & _
            '  "Charge" & vbTab & _
            '  ""
            'Dim peptideStr As String = "Peptide: " & curPep.AASequence
            'Dim toReturn As String = _
            '  peptideStr & vbCrLf & _
            '  vbCrLf & _
            '  headerStr & vbCrLf
            'Changed PM_REFACTOR 2005-01-25
            'Dim fragDumpSB As StringBuilder = New StringBuilder(3000)
            aInOutBufferToAddTo.Append("Peptide: ")

            'Changed PM_TAB_EXPORTFRAGMENTS 2005-12-21
            aInOutBufferToAddTo.Append(ControlChars.Tab)

            aInOutBufferToAddTo.Append(mPeptideSequence)
            aInOutBufferToAddTo.Append(ControlChars.NewLine)
            aInOutBufferToAddTo.Append(ControlChars.NewLine)


            'Changed PM_FRAGMENTS_PEPTIDEINFO 2007-03-22
            aInOutBufferToAddTo.Append(anInPeptideInfo)
            aInOutBufferToAddTo.Append(ControlChars.NewLine)


            aInOutBufferToAddTo.Append("Note: the MCR values are theoretical values transformed back to uncalibrated (so they match the spectrum).")
            aInOutBufferToAddTo.Append(ControlChars.NewLine)
            aInOutBufferToAddTo.Append(ControlChars.NewLine)

            aInOutBufferToAddTo.Append(ControlChars.NewLine)
            aInOutBufferToAddTo.Append("Seq")
            aInOutBufferToAddTo.Append(ControlChars.Tab)
            aInOutBufferToAddTo.Append("Ion")
            aInOutBufferToAddTo.Append(ControlChars.Tab)
            aInOutBufferToAddTo.Append("MCR")
            aInOutBufferToAddTo.Append(ControlChars.Tab)
            aInOutBufferToAddTo.Append("Charge")
            aInOutBufferToAddTo.Append(ControlChars.Tab)
            aInOutBufferToAddTo.Append("Matching peak")
            aInOutBufferToAddTo.Append(ControlChars.Tab)
            aInOutBufferToAddTo.Append(ControlChars.NewLine)

            If mDisplItmArr1 Is Nothing Then
                aInOutBufferToAddTo.Append("No current fragments!")
                aInOutBufferToAddTo.Append(ControlChars.NewLine)
            Else
                'Dim len As Integer = mDisplItmArr1.Length
                Dim lastIndex As Integer = mDisplItmArr1.Length - 1
                Dim j As Integer
                For j = 0 To lastIndex
                    Dim curItem As fragmentExStructure = mDisplItmArr1(j)

                    'Not in use...
                    ''Dim ionStr As String
                    'If curItem.Bion Then
                    '    'ionStr = "B"
                    '    aInOutBufferToAddTo.Append("B")
                    'Else
                    '    If curItem.Yion Then
                    '        'ionStr = "Y"
                    '        aInOutBufferToAddTo.Append("Y")
                    '    Else
                    '        Trace.Assert(False, "Stop!", "PIL ASSERT. Internal/development assert for stopping execution......")
                    '    End If
                    'End If

                    'Changed PM_REFACTOR 2005-01-25
                    'toReturn &= _
                    '  curItem.seq & vbTab & _
                    '  curItem.descStr & vbTab & _
                    '  curItem.mzCalcLoc & vbTab & _
                    '  curItem.charge & vbTab & _
                    '  vbCrLf
                    aInOutBufferToAddTo.Append(curItem.seq)
                    aInOutBufferToAddTo.Append(ControlChars.Tab)



                    aInOutBufferToAddTo.Append(curItem.descStr)
                    aInOutBufferToAddTo.Append(ControlChars.Tab)

                    aInOutBufferToAddTo.Append(curItem.MCRcalcLoc)
                    aInOutBufferToAddTo.Append(ControlChars.Tab)

                    aInOutBufferToAddTo.Append(curItem.charge)
                    aInOutBufferToAddTo.Append(ControlChars.Tab)

                    If curItem.ionMatched Then
                        aInOutBufferToAddTo.Append("YES")
                    Else
                        aInOutBufferToAddTo.Append("NO")
                    End If
                    aInOutBufferToAddTo.Append(ControlChars.Tab)

                    aInOutBufferToAddTo.Append(ControlChars.NewLine)
                Next j
            End If
        End Sub 'fragmentsSaveString


        'Changed PM_DTASC_COMPILE 2006-12-13
        '
        'Moved from signal.vb, to reduce dependencies, for DTASC update.
        'MM changed for MS3 20Apr2004
        '****************************************************************************
        '*    <placeholder for header>                                              *
        '****************************************************************************
        Private Shared Function matchesIon( _
          ByRef anInSignal As Generic.List(Of LCPeakInfoStructure), _
          ByVal aMass As Double, ByVal aMassAcc As Double, _
          ByRef anInMaxIntPeakList() As Integer) _
          As Boolean

            'Changed PM_TYPESAFE 2006-11-01
            'Old:
            '  ByRef anInSignal As ArrayList

            Dim toReturn As Boolean = False 'Default if nothing found.

            'Do a search in the list of top four fragment ions per 100 Da.
            Dim i As Integer
            Dim lastIndex As Integer = anInMaxIntPeakList.Length - 1
            For i = 0 To lastIndex
                'Dim theMass As Double = ExtractMassFromlstMSTopSignal(i)
                Dim indexIntoDataPoints As Integer = anInMaxIntPeakList(i)

                'Changed PM_MS3SCORING_USEPEAKS 2004-10-27
                'Dim theMass As Double = _
                '  DirectCast(anInSignal(indexIntoDataPoints), signalStructure).Xsig
                Dim mass As Double = _
                  anInSignal(indexIntoDataPoints).LCpeakTimeCentroid

                If mass > aMass + aMassAcc Then
                    Exit For 'Past upper bound, no need to continue.
                End If

                If mass > aMass - aMassAcc AndAlso mass < aMass + aMassAcc Then
                    toReturn = True
                    Exit For
                End If
            Next
            Return toReturn
        End Function 'matchesMS3Ion


        'Changed PM_DTASC_COMPILE 2006-12-13
        '
        'Moved from signal.vb, to reduce dependencies, for DTASC update.
        'MM changed for MS3 20Apr2004
        '****************************************************************************
        '*  SUBROUTINE NAME:   matchFragmentIons                                    *
        'd$ <summary>
        'd$   
        'd$   Purpose: xyz.
        'd$                 Note: cyclic dependence by having it here?
        'd$   
        'd$   <see cref="T:VBXMLDoc.CVBXMLDoc" />.
        'd$ </summary>
        Public Shared Sub matchFragmentIons( _
          ByRef anInSignal As Generic.List(Of LCPeakInfoStructure), _
          ByRef anInMaxIntPeakList() As Integer, _
          ByVal aPrecursorCharge As Integer, _
          ByVal aMassTol As Double, _
          ByRef aFragments As peptideFragments _
          )
            'Old:
            '  ByRef anInSignal As ArrayList

            'Dim massTol As Double = 0.4
            Dim massTol2 As Double = aMassTol


            'Changed PM_REFACTOR 2005-08-17
            ''Changed PM_REFACTOR 2005-02-25
            'Dim tokens As ArrayList = mMS3Fragments.getFragmentTokens(-10.0, 99999.9)
            Dim tokens As ArrayList = _
              aFragments.getFragmentTokens(45.0, 99999.9)

            Dim fragment As fragmentExStructure
            Dim token As Integer
            For Each token In tokens
                fragment = aFragments.getFragment(token)

                'fragIon = ExtractMassFromChkIonFrag(j)
                Dim fragIon As Double = fragment.MCRcalcLoc
                Dim matched As Boolean = _
                  matchesIon(anInSignal, fragIon, massTol2, anInMaxIntPeakList)

                If matched Then
                    Select Case fragment.ionType
                        Case ionTypeEnum.enumYion2
                            Dim peter2 As Integer = 2
                        Case ionTypeEnum.enumBion2
                            Dim peter2 As Integer = 2
                        Case ionTypeEnum.enumAion2
                            Dim peter2 As Integer = 2
                        Case ionTypeEnum.enumPrecursorIon2
                            'Do not match precursor
                            matched = False
                        Case Else
                            Trace.Assert(False, _
                              "PIL ASSERT. Select Case never fall-through")
                    End Select
                End If

                'Changed PM_MS3_CHARGE_RULES 2005-02-25
                'Apply rules about charge for precursor and its fragments, in this
                'case the precursor from MS2 and the MS3 fragment.
                If matched Then
                    If fragment.charge > aPrecursorCharge Then
                        matched = False
                    End If
                End If

                'Changed PM_REFACTOR 2005-02-25
                'mDisplItmArr1(j).ms3ionMatched = matched
                aFragments.markMatch(token, matched)
            Next 'tokens
        End Sub 'matchFragmentIons


    End Class 'peptideFragments


End Namespace 'massSpectrometryBase


    

    

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