/****************************************************************************
* Copyright (C) 2008 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: ion series are computed based on a data *
* driven approach. The data may be provided from *
* the outside, e.g. an XML file edited by a user. *
* This class does not know about any particular *
* ion-series, e.g. y or b ions... - this is specified *
* *
* Also handles a number of ion series tables where *
* the effective table is dependent on some rules. *
* E.g. one table with some neutral loses if the *
* peptide has a phosphorylation modification. *
* *
****************************************************************************/
/****************************************************************************
* 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: PILgeneralisedIonSeries.cs *
* TYPE: CSHARP *
* *
* CREATED: PM 2008-05-08 Vrs 1.0. *
* UPDATED: PM 2008-xx-xx *
* *
* *
****************************************************************************/
//Future:
// 1. Some rules (specified in datastructures or in the class itself)
// about some physically impossible ions, e.g. b1 ions for some
// amino acids.
//
// 2. Proline feaure...
//
// 3. Presense of precursor. Special case of yN? (start, end) = (-1, -1)
//
// 4. Rename yIonArray() and bIonArray() to a more general name
// as e.g. z- og c-ions are now handled. Rename to backwardIonArray()
// and forwardIonArray().
//
// 5.
using System.Collections.Generic; //For List and Dictionary.
using System.Diagnostics; //For Trace. And its Assert.
//using MolecularSharedStructures; //For modificationCountStruct.
using massSpectrometryBase.quantitation;
/****************************************************************************
* <placeholder for header> *
****************************************************************************/
namespace massSpectrometryBase
{
//Changed PM_REFACTOR 2008-05-10. Moved from somewhere else.
/****************************************************************************
* <placeholder for header> *
****************************************************************************/
namespace quantitation
{
public struct AAsetStruct
{
public string AAs;
public double diffFromBase3;
//Changed PM_TERMMOD_FRAGMENTMASS_TROUBLE 2007-09-14
//Peptide modification dependent helper field.
public int INTERNAL_startPosition3;
public int INTERNAL_endPosition3;
//Note: even though this information is also in the
// container structure, quantModificationStructure, there
// are places in the program where only a list of
// AAsetStructure is available.
//Later perhaps:
// Dim absoluteMass As Double
// Dim absoluteMassByComposition As xyz By integer ID?
// Dim compositionDiffFromBase As xyz By integer ID?
//Selector for the type of mass?: dim massType as enumMassType
} //struct AAsetStruct
} //namespace quantitation
//Changed PM_REFACTOR 2008-05-10. Moved from file peptideFragments.vb.
//Changed PM_DTASC_COMPILE 2006-07-04. Moved here to avoid
//dependency in DTASC.
public struct ionSetStruct
{
public double[] forwardIonDiffs;
public double[] backwardIonDiffs;
//Index into list of combItemStructure
public int compVectorIndex;
//So client can later return to a return item.
public int ID;
//Dragged along here. For convenience.
public double score;
} //ionSetStruct
//Changed PM_REFACTOR 2008-05-08 Moved from somewhere else.
////Changed PM_REFACTOR 2005-01-26
/****************************************************************************
* <placeholder for header> *
****************************************************************************/
public enum ionTypeEnum
{
enumYion2 = 257,
enumBion2,
enumAion2,
enumPrecursorIon2
//Not yet..
//'Changed PM_QUANT_CHARGE_DISPLAY 2005-03-14
//eCustom 'For overriding colour and other visual display things.
} //ionTypeEnum
//Changed PM_REFACTOR 2008-05-08. Moved from file MMaaSequence.vb.
// //Changed PM_DTASC_COMPILE 2008-02-11. Moved to here
// // from peptideFragments.vb to avoid dependencies
// // with DTASC. But is this a good place???
// // In DTASC the dependency is from class SDUPspectrumMarking
// // and class frmSpectrumDisplay.
/****************************************************************************
* <placeholder for header> *
****************************************************************************/
public struct fragmentExStructure
{
public double MCRcalcLoc;
//Changed PM_REFACTOR 2005-02-24. Now computed on the client side.
//Dim yLoc As Double
//Not cuurently used.
//Dim MCRobsLoc As Double
//Dim deltaMass As Double
public string seq;
public string descStr;
public int charge;
////Enumeration instead of Bion and Yion
//Dim Yion As Boolean
//Dim Bion As Boolean
//Dim precursorIon As Boolean
public ionTypeEnum ionType; //Note: we keep it for now. Works
// OK for special things for precursors and for colouring.
//Helper field.
public bool ionMatched;
//Changed PM_FRAGMENTDISPLAY 2008-05-18
public int yDisplayLevel2;
public int yDisplayLevelForMatching2;
} //fragmentExStructure
/****************************************************************************
* Purpose: represents a single ion series
*
****************************************************************************/
public struct singleIonSeriesStructure
{
public bool useModSeqRule; //Whether or not fragment amino acids
// sequences for this ion series need to contain one or more of
// the amino acids affected by the matched modification (for the
// entire ion series table).
public int ionSeriesID2;
public string ionSeriesName;
public string shortName2; //E.g. "y", "b", "c" or "z".
public string postFix; //E.g. "-98", "-phos", "-H20" or "-NH2".
//Also allow specification by composition?
public double offsetFromResidueToNeutral; //E.g. +18 Da for y-series.
//The charge transform is done
//in code, not by specification.
//But any value can be specified,
//it just need some
public bool forward; //true: forward. false: backward. Use enum instead?
public int colour; //For display and currently also implies
//forward/backward (e.g. for MS3 scoring - in
//matchFragmentIons()).
//Some code for colour. Use RGB?
//
//For now: internal code:
// 419 y
// 421 b
// 431 a
// 433 precursor
//Changed PM_FRAGMENTDISPLAY 2008-05-18
public int yDisplayLevel4;
//Effective values for ***older*** versions of the
//application (in code):
// 0: b-ions
// 1: y-ions
// 2: y++ -ions
public int yDisplayLevelForMatching4;
public bool isPrecursorDerived;
public int charge;
//Constraints for using a subset of the whole ion series -
//corresponding to subset of the peptide.
public int startIonNumber; //1 for first ion, e.g. y1.
// Negative: from N. -3 for yN-3, y14 for a 17 long peptide.
public int endIonNumber; //1 for first ion, e.g. y1.
// Negative: from N. -3 for yN-3, y14 for a 17 long peptide.
//Neutral mass constraint. Using a subset of the whole ion
//series - corresponding to subset of the peptide.
public double startMass; //Positive for absolute mass. Negative for
//difference from neutral precursor mass.
public double endMass; //Positive for absolute mass. Negative for
//difference from neutral precursor mass.
//Constraints for the number of modifications. This is a condition
//whether the whole ion series should be used or not. E.g. only
//use y-196 (2 x phosphorylation loss) if the number of
//modifications (the matched one) is 2 or more.
public int startMods2; //
public int endMods2; //
} //struct singleIonSeriesStructure
/****************************************************************************
* Purpose: a single rule for matching an ion series table.
*
****************************************************************************/
public struct matchRuleStructure
{
public int matchModID; //Reference to a modification. -1 means
// anything, even non-modified. That is: it will always match and
// as such the default ion set can be specified by this way.
//The number of modifications in the peptide (for the match
//modification - field above) must be within this range:
//Not yet.
//public int startMods7;
//public int endMods7;
//What was this for??
//public string matchString3; //Regular expression.
//Changed PM_GENERALISED_IONSERIES_SPECTRUMCLASSIFICATION 2008-06-23
public spectrumSubTypeEnum MSMSspectrumClassification;
//Changed PM_MARKER_SPECTRUMCLASSIFICATION 2008-06-23
//We need to refactor, possibly the whole
// of spectrumClassifier.vb. At least spectrumTypeEnum and
// spectrumSubTypeEnum.
} //struct matchRuleStructure
/****************************************************************************
* Purpose: represents a particular set of ions (e.g. only a2, all
* single charged y-ions, double charged y-ions with
* neutral mass less than 700 Da or another set, e.g. single
* charged y-ions and single charged y-ions with 98 Da loss.
*
* Used for specifying .
*
****************************************************************************/
public struct ionSeriesTableStructure
{
public int ionTableID;
public string ionTableName;
public List<matchRuleStructure> rules2; //Rules as to whether this
//table should be used for computing the set of ions. E.g. a
//particular one if a peptide has a phosphorylation modification.
//Changed PM_REFACTOR 2008-06-23. To reduce redundancy (several
// rules using the same ion-series (e.g. y-series) we now have
// the ion series in a separate place and refer to them here
// by an ID (integer))
//
////A number of ion series for this ion table.
//public List<singleIonSeriesStructure> ionSeries;
public List<int> ionSeries2;
} //struct ionSeriesTableStructure
//Changed PM_REFACTOR 2008-10-09
/****************************************************************************
* Purpose: have all related to ion series in a single structure
*
* Used for specifying .
*
****************************************************************************/
public struct ionDefinitionsStructure
{
public List<ionSeriesTableStructure> ionTables;
public List<singleIonSeriesStructure> singleIonSeries;
} //struct ionDefinitionsStructure
/****************************************************************************
* <placeholder for header> *
****************************************************************************/
public class PILgeneralisedIonSeries
{
//Changed PM_REFACTOR 2008-10-09
// private List<ionSeriesTableStructure> mIonTables2;
//
// //Changed PM_REFACTOR 2008-06-23. Now two level defition (to reduce
// //redundancy).
// private List<singleIonSeriesStructure> mSingleIonSeries;
private ionDefinitionsStructure mIonDefs;
private List<string> mChargeStrings;
//Outer pair is (modification code, [info]).
//[info]: list of amino acids that the modification affects.
private Dictionary<int, List<string>> mModHash;
private quantitation.QuantitationModes_moreGeneral mQuantObject;
//Changed PM_CODEBRANCH 2007-10-26.
const bool CODEBRANCH_FIXED = true;
//Normally True. Can be set to false to reproduce a bug... This
//constant should be removed soon.
//****************************************************************************
//* SUBROUTINE NAME: New *
//d$ <summary>Constructor</summary>
public PILgeneralisedIonSeries(
ref quantitation.QuantitationModes_moreGeneral anInQuantObject,
ionDefinitionsStructure anInIonDefs
)
: base()
{
mQuantObject = anInQuantObject;
//Build strings for charge notation, for easy lookup (and saving memory!!).
{
int len = 20;
mChargeStrings = new List<string>(len);
string chstr = "";
for (int i = 0; i < len; i++)
{
chstr += "+";
mChargeStrings.Add(chstr);
}
}
Trace.Assert(
anInIonDefs.ionTables != null &&
anInIonDefs.ionTables.Count > 0,
"PIL ASSERT. anInIonDefs.ionTables is undefined or empty.");
Trace.Assert(
anInIonDefs.singleIonSeries != null &&
anInIonDefs.singleIonSeries.Count > 0,
"PIL ASSERT. anInIonDefs.singleIonSeries is undefined or empty.");
//Changed PM_PERSIST_IONSERIES 2008-10-09
////For now until we can read in the definitions from an XML file.
////Changed PM_REFACTOR 2008-10-09
////defaultIonTables(out mIonTables2, out mSingleIonSeries);
//mIonDefs = defaultIonTables();
mIonDefs = anInIonDefs;
mModHash = new Dictionary<int, List<string>>();
} //Constructor.
//****************************************************************************
//* <placeholder for header> *
//* anInModificationsList: type is simpleModificationSpecification *
//* *
//****************************************************************************
private static List<double> constructMassTable(
ref List<List<AAsetStruct>> anInModificationsList)
{
//Changed PM_QUANTGENERAL_PREPARATION 2006-07-14
//Old:
// ByRef anInModificationsList As ArrayList
//Changed PM_MEMORY_EFFICIENCY_256 2006-10-31
//Dim massTable(256) As Double
int len = 124;
List<double> massTable = new List<double>();
//Corresponding to z. Could it even
// be less, 91 for Z ?
//Changed PM_REFACTOR 2008-05-17
for (int i = 0; i < len; i++)
{
massTable.Add(0.0);
}
//Note: this is repeated in SetAAMassTable()s!!!!
{
//Default masses
massTable[(int)('A')] = MSconstants.ALA_MONO_MASS;
massTable[(int)('C')] = MSconstants.CYS_CARBAMIDOMETHYL_MONO_MASS;
//We assume Cys-carbamido as a fixed modication in the Mascot search.
massTable[(int)('D')] = MSconstants.ASP_MONO_MASS;
massTable[(int)('E')] = MSconstants.GLU_MONO_MASS;
massTable[(int)('F')] = MSconstants.PHE_MONO_MASS;
massTable[(int)('G')] = MSconstants.GLY_MONO_MASS;
massTable[(int)('H')] = MSconstants.HIS_MONO_MASS;
massTable[(int)('I')] = MSconstants.IIE_MONO_MASS;
massTable[(int)('K')] = MSconstants.LYS_MONO_MASS;
massTable[(int)('L')] = MSconstants.LEU_MONO_MASS_NORMAL;
massTable[(int)('M')] = MSconstants.MET_MONO_MASS_NORMAL;
massTable[(int)('N')] = MSconstants.ASN_MONO_MASS;
massTable[(int)('P')] = MSconstants.PRO_MONO_MASS;
massTable[(int)('Q')] = MSconstants.GLN_MONO_MASS;
massTable[(int)('R')] = MSconstants.ARG_MONO_MASS_NORMAL;
massTable[(int)('S')] = MSconstants.SER_MONO_MASS;
massTable[(int)('T')] = MSconstants.THR_MONO_MASS;
massTable[(int)('V')] = MSconstants.VAL_MONO_MASS;
massTable[(int)('W')] = MSconstants.TRP_MONO_MASS;
massTable[(int)('Y')] = MSconstants.TYR_MONO_MASS;
//Changed PM_SNIPS_OUJ_RKN 2006-11-29
massTable[(int)('U')] = MSconstants.LYS_MONO_MASS; //As K
massTable[(int)('O')] = MSconstants.ARG_MONO_MASS_NORMAL; //As R
massTable[(int)('J')] = MSconstants.ASN_MONO_MASS; //As N
}
{
//Apply modifications
//Outer loop: for each modification
foreach ( List<AAsetStruct> someModItem in anInModificationsList)
{
//Changed PM_QUANTGENERAL_PREPARATION 2006-07-14
//Dim someModItem As quantitation.simpleModificationSpecification
//Inner loop: for each AA set (usually only one, but 20 for N15)
foreach (AAsetStruct someAAset in someModItem)
{
//Changed PM_MULTIPLE_AA_FOR_MODIFICATION 2005-08-10
//Changed PM_QUANTGENERAL_PREPARATION 2006-07-14
//Dim AA As String = someModItem.AA
string AA = someAAset.AAs;
int lastIndex = someAAset.AAs.Length - 1;
int j;
for (j = 0; j <= lastIndex; j++)
{
if (lastIndex > 0)
{
//Optimisation as for most
// modifications there is only one AA (in
// that case it is already set).
AA = someAAset.AAs.Substring(j, 1);
}
//int index = (int)((char)AA);
int index = (int)(AA[0]);
double oldValue = massTable[index];
double diffFromBase = someAAset.diffFromBase3;
double newValue = oldValue + diffFromBase;
//Changed PM_HYSTAG_BADMASS 2005-07-07. For now: until we
//get rid of explicit Carbamido-Cys in the code we assume
//that .
// The condition is effectively detection of
// baseModification greater than 0. Or in order
// words HysTag/ICAT like quantitation modes.
//
//Changed PM_120DA_RULE 2007-09-12. Partly fixed, but
// not a fundamental fix. This will wait until fixed
// modificatios are read in from the Mascot result
// file and the Carbamido-Cys assumption can be removed
// all over the code.
//
//'Changed PM_UBIK_ASSERT 2006-03-28
//'Changed PM_NOT_HYSTAG_FOR_PHOSPHO 2005-07-20
//'If someModItem.diffFromBase > 30.0 Then
//'If someModItem.diffFromBase > 100.0 Then
//If diffFromBase > 120.0 Then
//If diffFromBase > 30.0 AndAlso (AA = "C" OrElse AA = "c") Then
if (diffFromBase > 100.0 && (AA == "C" || AA == "c"))
{
// This is a detection of wether fixed mod Carbamido has
// been used or not.
// Not 30.0: Acetyl N-term is 42 Da!
//
//The mass limit is to allow lower mass modifications to
//act on Cysteine, e.g. N15 on Carbamido-Cys.
//This is for ICAT, HysTag and similar. In this case
//it is assumed that Carbamidomethyl is ***not***
//a fixed modification. In all other cases this
//fixed modification for Cys is assumed.
//newValue = diffFromBase This made the diff specification
// into an absolute value!
newValue =
MSconstants.CYS_MONO_MASS_NORMAL + diffFromBase;
}
massTable[index] = newValue;
} //Through AA set.
} //Through someModItem.
} //Through modifications.
}
return massTable;
} //constructMassTable()
//Changed PM_REFACTOR 2008-05-17. Moved from file MMaaSequence.vb
//Changed PM_REFACTOR_GLOBALS 2003-10-09
//****************************************************************************
//* <placeholder for header> *
//****************************************************************************
public static void effectiveMasses(
string aModStr,
out double anOutArgMass,
out double anOutLeuMass,
out double anOutMetMass,
out double anOutCysMass)
{
anOutArgMass = MSconstants.ARG_MONO_MASS_NORMAL;
anOutLeuMass = MSconstants.LEU_MONO_MASS_NORMAL;
anOutMetMass = MSconstants.MET_MONO_MASS_NORMAL;
//Changed PM_CYS_TROUBLE 2003-11-14
//anOutCysMass = CYS_MONO_MASS_NORMAL
anOutCysMass = -1000000000.0;
string lowerModStr = aModStr.ToLower();
if (lowerModStr.IndexOf("arg") >= 0)
{
anOutArgMass = MSconstants.ARG_C6_MONO_MASS;
}
if (lowerModStr.IndexOf("leu") >= 0)
{
//assume single D3 modification for now
anOutLeuMass = MSconstants.LEU_D3_MONO_MASS;
}
if (lowerModStr.IndexOf("ox") >= 0)
{
anOutMetMass = MSconstants.MET_OX_MONO_MASS;
}
//Changed PM_CYS_TROUBLE 2003-11-20
bool someCys = false;
if (lowerModStr.IndexOf("(c)") >= 0)
{
someCys = true;
}
if (lowerModStr.IndexOf("cys") >= 0)
{
someCys = true;
}
if (someCys)
{
if (lowerModStr.IndexOf("carbamido") >= 0)
{
anOutCysMass = MSconstants.CYS_CARBAMIDOMETHYL_MONO_MASS;
}
else
{
//Changed PM_CYS_TROUBLE 2003-11-14
if (lowerModStr.IndexOf("nocysmod") >= 0)
{
anOutCysMass = MSconstants.CYS_MONO_MASS_NORMAL;
}
else
{
if (lowerModStr.IndexOf("cyshy0") >= 0)
{
//Changed PM_HYSTAG_BADMASS 2005-07-07
//anOutCysMass = CYS_CARBAMIDOMETHYL_MONO_MASS + CYS_HYS_ALA_D0
anOutCysMass = MSconstants.CYS_HYS_ALA_D0;
}
else
{
if (lowerModStr.IndexOf("cyshy4") >= 0)
{
//Changed PM_HYSTAG_BADMASS 2005-07-07
//anOutCysMass = CYS_CARBAMIDOMETHYL_MONO_MASS + CYS_HYS_ALA_D4
anOutCysMass = MSconstants.CYS_HYS_ALA_D4;
}
else
{
Trace.Assert(false, "PIL ASSERT. Cysteine modification not explicit!.");
}
}
}
}
}
else
{
int peter4 = 4;
anOutCysMass = MSconstants.CYS_CARBAMIDOMETHYL_MONO_MASS;
}
} //effectiveMasses()
//Changed PM_REFACTOR 2008-05-16. Moved from peptideFragments.vb.
//****************************************************************************
//* <placeholder for header> *
//* anInModificationsList: type is simpleModificationSpecification *
//* *
//****************************************************************************
public static void backwardIonArray(
ref string anInSeq,
out List<double> anOutFragMasses2,
out int aOutMaxCalcArrIdx,
string aModStr,
ref List<List<AAsetStruct>> anInModificationsList,
bool aMS3_BionFlag)
{
//Old type for anOutFragMasses:
// anOutFragMasses() As Double
//This function takes the peptide sequence as input and fills an
//allocated array with doubles for Y ion masses.
//'Changed PM_GENERALISED_QUANT_MODE 2003-12-10
//'Changed PM_CYS_TROUBLE 2003-11-14
//Dim modStrToUse As String = aModStr
//If modStrToUse = "" Then
// modStrToUse = "noCysMod"
//End If
//'Changed PM_REFACTOR_GLOBALS 2003-10-09
//Dim argEffectiveMass As Double
//Dim leuEffectiveMass As Double
//Dim metEffectiveMass As Double
//Dim cysEffectiveMass As Double
//effectiveMasses(modStrToUse, _
// argEffectiveMass, leuEffectiveMass, metEffectiveMass,
// cysEffectiveMass)
//Why is effectiveMasses not called ??? (it is for b-ions...)
//Changed PM_GENERALISED_QUANT_MODE 2003-12-10
List<double> massTable = constructMassTable(ref anInModificationsList);
//Name it backwardIonMass?
double yIonMass = MSconstants.Y_ION_OFFSET;
//Changed PM_MS3_DTASUPERCHARGE 2004-04-15
if (aMS3_BionFlag)
{
yIonMass = MSconstants.B_ION_OFFSET;
//In the case of y ions from b-ion
// precusors, the mass is like an internal fragment.
}
//Changed PM_BAD_PRECURSORMASS 2006-10-31.
//'Changed PM_INFINITE_FRAGMENTS 2005-08-09
// '' It is aSeq.Length - 2 because zero based array and n-1 y ions
// '' for seq of length n.
//'aMaxCalcArrIdx = _
//' Math.Min(aSeq.Length - 2, MAX_Y_IONS_TO_DISPLAY - 1) 'Limit to an
//' array of currently 100 Y ions.
//aOutMaxCalcArrIdx = aSeq.Length - 2
int plen = anInSeq.Length;
//Changed PM_REFACTOR 2008-05-08
anOutFragMasses2 = new List<double>(plen);
int lastIndex = plen - 1;
aOutMaxCalcArrIdx = lastIndex;
//Include yN in the computation
int i;
//Changed PM_BAD_PRECURSORMASS 2006-10-31
//For i = aOutMaxCalcArrIdx + 1 To 1 Step -1
// Fill the array
// from y1 to yn-1 (if we did it to 0 then we would get
// the single protonated mass as well.
for (i = lastIndex; i >= 0; i += -1)
{
//Include yN.
//Changed PM_REFACTOR 2008-05-17
//char curAA = anInSeq.Chars(i);
char curAA = anInSeq[i];
//Changed PM_REFACTOR 2008-05-17
//double curMass = massTable(Strings.AscW(curAA));
double curMass = massTable[(int)curAA];
yIonMass += curMass;
//Changed PM_REFACTOR 2008-05-08
//anOutFragMasses(lastIndex - i) = yIonMass
anOutFragMasses2.Add(yIonMass);
}
//Changed PM_TERMMOD_FRAGMENTMASS_TROUBLE 2007-09-14
{
//Undo for modifications that do not span the entire
// peptide sequence, e.g. terminal modifications. In this
// case we can still use our mass table above for majority of
// the calculations.
foreach (
List<AAsetStruct> someModItem in anInModificationsList)
{
bool allPositions = false; //Keep compiler happy.
int startPos0 = -1; //Flag for below.
int endPos0 = -1; //Keep compiler happy.
foreach ( AAsetStruct someAAset in someModItem)
{
if (startPos0 == -1)
{
//-1 is a flag - we only use the
// first item in the someModItem list. It is the only
// item for which the INTERNAL fields are defined.
int maxMods;
PILpeptide.findPositionsEtc(
someAAset.INTERNAL_startPosition3,
someAAset.INTERNAL_endPosition3,
plen,
out allPositions,
out startPos0,
out endPos0,
out maxMods);
}
else
{
int peter2 = 2;
//E.g. for N15
}
if (!allPositions)
{
foreach (char someAA in someAAset.AAs)
{
double corrMass = 0.0;
bool corrMassIsZero = true;
for (i = lastIndex; i >= 0; i += -1)
{
//Include yN.
//Dim oneBaseIndex As Integer = i + 1
bool insideRange = i >= startPos0 &&
i <= endPos0;
if (!insideRange)
{
//Changed PM_REFACTOR 2008-05-17
//char curAA = anInSeq.Chars(i);
char curAA = anInSeq[i];
if (someAA == curAA)
{
//New correction mass.
corrMass += someAAset.diffFromBase3;
corrMassIsZero = false;
}
//Changed PM_CODEBRANCH 2007-10-26.
if (!CODEBRANCH_FIXED)
{
//Changed PM_IMPOSSIBLELOWMASS_ASSERT 2007-10-26. Old location.
if (!corrMassIsZero)
{
anOutFragMasses2[lastIndex - i] -= corrMass;
}
}
}
else
{
//Inside range. The correction mass should
//not be updated, but we still need to
//correct the fragment mass (done just
//below) as fragment masses are
//accumulative - as the mass of an amino
//acid residue affects ALL higher mass
//fragments.
int peter3 = 3;
}
//Changed PM_CODEBRANCH 2007-10-26.
if (CODEBRANCH_FIXED)
{
//Changed PM_IMPOSSIBLELOWMASS_ASSERT 2007-10-26.
//Moved out to this level.
if (!corrMassIsZero)
{
anOutFragMasses2[lastIndex - i] -= corrMass;
}
}
}
//Through peptide sequence.
}
//Through affected AAs for a modification, usually
// only one. But 20 for N15.
}
//Modification with not all positions in peptide.
}
//Through one modification - through sets of ***different***
// mass diffs.
}
//Through modifications.
} //Block, undoing some fragment massses.
} //backwardIonArray()
//****************************************************************************
//* <placeholder for header> *
//* anInModificationsList: type is simpleModificationSpecification *
//****************************************************************************
public static void forwardIonArray(
ref string anInSeq,
out List<double> anOutFragMasses3,
out int anOutMaxCalcArrIdx,
string aModStr,
ref List<List<AAsetStruct>> anInModificationsList)
{
//Old type for anOutFragMasses2:
// anOutFragMasses2() As Double
//This function takes the peptide sequence as input and fills an
//allocated array with doubles for b ion masses up to a maximum of 100 b ions.
//this is so that no array needs to created or re-dimensioned which would
//take time
//Changed PM_CYS_TROUBLE 2003-11-14
string modStrToUse = aModStr;
if (modStrToUse == "")
{
modStrToUse = "noCysMod";
}
//Changed PM_REFACTOR_GLOBALS 2003-10-09
double argEffectiveMass;
double leuEffectiveMass;
double metEffectiveMass;
double cysEffectiveMass;
effectiveMasses(
modStrToUse,
out argEffectiveMass,
out leuEffectiveMass,
out metEffectiveMass,
out cysEffectiveMass);
//Changed PM_GENERALISED_QUANT_MODE 2003-12-10
List<double> massTable = constructMassTable(ref anInModificationsList);
//Name it forwardIonMass?
double BionMass = MSconstants.B_ION_OFFSET;
int i;
// It is aSeq.Length - 2 because zero based array and n-1 y ions
// for seq of length n.
//Changed PM_INFINITE_FRAGMENTS 2005-08-09
//'Limit to an array of currently 100 b ions.
//maxCalcArrIdx = Math.Min(aSeq.Length - 2, MAX_Y_IONS_TO_DISPLAY - 1)
int plen = anInSeq.Length;
//'Changed PM_UNITTESTS 2008-05-20Changed PM_UNITTESTS 2008-05-20
//anOutMaxCalcArrIdx = plen - 2;
anOutMaxCalcArrIdx = plen - 1; //Do include bN. For generalised ion series.
//Changed PM_REFACTOR 2008-05-08
anOutFragMasses3 = new List<double>(plen);
for (i = 0; i <= anOutMaxCalcArrIdx; i++)
{
// + 1
//Changed PM_REFACTOR 2008-05-17
//char curAA = anInSeq.Chars(i);
char curAA = anInSeq[i];
//Changed PM_REFACTOR 2008-05-17
//double curMass = massTable[Strings.AscW(curAA)];
double curMass = massTable[(int)curAA];
BionMass += curMass;
//Changed PM_REFACTOR 2008-05-08
//anOutFragMasses2(i) = BionMass
anOutFragMasses3.Add(BionMass);
}
//Changed PM_TERMMOD_FRAGMENTMASS_TROUBLE 2007-09-14
{
//Undo for modifications that do not span the entire
// peptide sequence, e.g. terminal modifications. In this
// case we can still use our mass table above for majority of
// the calculations.
foreach ( List<AAsetStruct> someModItem in anInModificationsList)
{
int startPos0 = -1; //Flag for below.
int endPos0 = -1; //Keep compiler happy.
//Just in case.
bool allPositions = false; //Keep compiler happy.
foreach (
AAsetStruct someAAset in someModItem)
{
if (startPos0 == -1)
{
//-1 is a flag - we only use the
// first item in the someModItem list. It is the only
// item for which the INTERNAL fields are defined.
int maxMods;
PILpeptide.findPositionsEtc(
someAAset.INTERNAL_startPosition3,
someAAset.INTERNAL_endPosition3,
plen,
out allPositions,
out startPos0,
out endPos0,
out maxMods);
}
else
{
int peter2 = 2;
//E.g. for N15
}
if (!allPositions)
{
foreach (char someAA in someAAset.AAs)
{
double corrMass = 0.0;
bool corrMassIsZero = true;
for (i = 0; i <= anOutMaxCalcArrIdx; i++)
{
bool insideRange = i >= startPos0 && i <= endPos0;
if (!insideRange)
{
//Changed PM_REFACTOR 2008-05-17
//char curAA = anInSeq.Chars(i);
char curAA = anInSeq[i];
if (someAA == curAA)
{
//New correction mass.
corrMass += someAAset.diffFromBase3;
corrMassIsZero = false;
}
//Changed PM_CODEBRANCH 2007-10-26.
if (!CODEBRANCH_FIXED)
{
//Changed PM_IMPOSSIBLELOWMASS_ASSERT 2007-10-26. Old location.
if (!corrMassIsZero)
{
anOutFragMasses3[i] -= corrMass;
}
}
}
else
{
//Inside range. The correction mass should
//not be updated, but we still need to
//correct the fragment mass (done just
//below) as fragment masses are
//accumulative - as the mass of an amino
//acid residue affects ALL higher mass
//fragments.
int peter3 = 3;
}
//Changed PM_CODEBRANCH 2007-10-26.
if (CODEBRANCH_FIXED)
{
//Changed PM_CODEBRANCH 2007-10-26. Moved out to this level.
if (!corrMassIsZero)
{
anOutFragMasses3[i] -= corrMass;
}
}
} //Through peptide sequence.
} //Through affected AAs for a modification, usually
// only one. But 20 for N15.
} //Modification with not all positions in peptide.
} //Through one modification - through sets of ***different***
// mass diffs.
} //Through modifications.
} //Block, undoing some fragment massses.
} //forwardIonArray()
//Changed PM_PERSIST_IONSERIES 2008-10-10
//****************************************************************************
//* SUBROUTINE NAME: addSingleChargedYionSeries
//d$ <summary>Helper function for the functions below, e.g.
// returns "triple" for an input of 3. </summary>
//
//****************************************************************************
private static string chargeWord(int aCharge)
{
//Use (static) hash instead of this function??
string toReturn = ""; //Safe value.
switch (aCharge)
{
case 0:
toReturn = "Neutral";
break;
case 1:
toReturn = "Single";
break;
case 2:
toReturn = "Double";
break;
case 3:
toReturn = "Triple";
break;
case 4:
toReturn = "Quadrouple";
break;
default:
toReturn = "Multiple";
break;
} //switch
toReturn += " charged";
return toReturn;
}
//****************************************************************************
//* SUBROUTINE NAME: addSingleChargedYionSeries
//d$ <summary>Add definition for common ion-series: single charged y-ions</summary>
//
//****************************************************************************
private static void addSingleChargedYionSeries(
ref List<singleIonSeriesStructure> anInOutIonTables,
int anIonSeriesID
)
{
{ //Single charged y-ions.
singleIonSeriesStructure fullYseries;
//Changed PM_REFACTOR 2008-06-23
//fullYseries.ionSeriesID = 1201;
fullYseries.ionSeriesID2 = anIonSeriesID;
fullYseries.ionSeriesName = "Single charged full y series.";
fullYseries.shortName2 = "y";
fullYseries.postFix = "";
fullYseries.offsetFromResidueToNeutral =
MSconstants.NORMAL_C_TERMINUS_MONO +
MSconstants.NORMAL_N_TERMINUS_MONO; //18 Da, Water.
fullYseries.forward = false;
fullYseries.colour = 419;
fullYseries.isPrecursorDerived = false;
fullYseries.charge = 1;
//fullYseries.startAA = 1 + 4; //Start with y5.
fullYseries.startIonNumber = 1 + 0; //Start with y1.
fullYseries.endIonNumber = -1 - 1; //Not yN.
fullYseries.startMass = 0.1;
fullYseries.endMass = -0.1;
//No rule for number of modifications.
fullYseries.startMods2 = 0;
fullYseries.endMods2 = 999;
fullYseries.useModSeqRule = false;
//Changed PM_FRAGMENTDISPLAY 2008-05-18
fullYseries.yDisplayLevel4 = 0; //2-1
fullYseries.yDisplayLevelForMatching4 = 4;
anInOutIonTables.Add(fullYseries);
}
} //addSingleChargedYionSeries().
//Later: refactor; merge with addSingleChargedYionSeries().
//****************************************************************************
//* SUBROUTINE NAME: addDoubleChargedYionSeries
//d$ <summary>Add definition for common ion-series: double charged
// y-ions below a certain mass limit</summary>
//
//****************************************************************************
private static void addDoubleChargedYionSeries(
ref List<singleIonSeriesStructure> anInOutIonTables,
int anIonSeriesID,
double aMinMass
)
{
{ //Mass restricted double charged y series.
singleIonSeriesStructure YdoubleSeries;
//Changed PM_REFACTOR 2008-06-23
//YdoubleSeries.ionSeriesID = 1210;
YdoubleSeries.ionSeriesID2 = anIonSeriesID;
YdoubleSeries.ionSeriesName = "Double charged mass restricted y series.";
YdoubleSeries.shortName2 = "y";
YdoubleSeries.postFix = "";
YdoubleSeries.offsetFromResidueToNeutral =
MSconstants.NORMAL_C_TERMINUS_MONO +
MSconstants.NORMAL_N_TERMINUS_MONO; //18 Da, Water.
YdoubleSeries.forward = false;
YdoubleSeries.colour = 419;
YdoubleSeries.isPrecursorDerived = false;
YdoubleSeries.charge = 2;
//YdoubleSeries.startAA = 1 + 4; //Start with y5.
YdoubleSeries.startIonNumber = 1 + 0; //Start with y1.
YdoubleSeries.endIonNumber = -1 - 1; //Not yN.
YdoubleSeries.startMass = aMinMass;
YdoubleSeries.endMass = -0.1;
//No rule for number of modifications.
YdoubleSeries.startMods2 = 0;
YdoubleSeries.endMods2 = 999;
YdoubleSeries.useModSeqRule = false;
//Changed PM_FRAGMENTDISPLAY 2008-05-18
YdoubleSeries.yDisplayLevel4 = 0;
//Changed PM_LEVEL_FOR_MATCHED_DOUBLE_YIONS 2008-10-22
//YdoubleSeries.yDisplayLevelForMatching4 = 0; //3
YdoubleSeries.yDisplayLevelForMatching4 = 1;
anInOutIonTables.Add(YdoubleSeries);
}
} //addDoubleChargedYionSeries().
//****************************************************************************
//* SUBROUTINE NAME: addSingleChargedBionSeries
//d$ <summary>Add definition for common ion-series: single charged b-ions</summary>
//
//****************************************************************************
private static void addSingleChargedBionSeries(
ref List<singleIonSeriesStructure> anInOutIonTables,
int anIonSeriesID
)
{
//Single charged b-ions.
singleIonSeriesStructure fullBseries;
//Changed PM_REFACTOR 2008-06-23
//fullBseries.ionSeriesID = 2001;
fullBseries.ionSeriesID2 = anIonSeriesID;
fullBseries.ionSeriesName = "Single charged full b series.";
fullBseries.shortName2 = "b";
fullBseries.postFix = "";
fullBseries.offsetFromResidueToNeutral = 0.0;
fullBseries.forward = true;
fullBseries.colour = 421;
fullBseries.isPrecursorDerived = false;
fullBseries.charge = 1;
fullBseries.startIonNumber = 1 + 0; //Start with b1.
fullBseries.endIonNumber = -1 - 1; //Not bN.
fullBseries.startMass = 0.1;
fullBseries.endMass = -0.1;
//No rule for number of modifications.
fullBseries.startMods2 = 0;
fullBseries.endMods2 = 999;
fullBseries.useModSeqRule = false;
//Changed PM_FRAGMENTDISPLAY 2008-05-18
fullBseries.yDisplayLevel4 = 0; //1
fullBseries.yDisplayLevelForMatching4 = 4;
anInOutIonTables.Add(fullBseries);
} //addSingleChargedBionSeries().
//****************************************************************************
//* SUBROUTINE NAME: addA2ionSeries
//d$ <summary>Add definition for common ion-series: single charged b-ions</summary>
//
//****************************************************************************
private static void addA2ionSeries(
ref List<singleIonSeriesStructure> anInOutIonTables,
int anIonSeriesID
)
{
{ //Single charged a2 ion.
singleIonSeriesStructure a2series;
//Changed PM_REFACTOR 2008-06-23
//a2series.ionSeriesID = 3001;
a2series.ionSeriesID2 = anIonSeriesID;
a2series.ionSeriesName = "Single charged a2 only... (as in a2/b2 pair).";
a2series.shortName2 = "a";
a2series.postFix = "";
a2series.offsetFromResidueToNeutral = -MSconstants.CO_MASS_MONO;
a2series.forward = true;
a2series.colour = 431;
a2series.isPrecursorDerived = false;
a2series.charge = 1;
//a2 only!
a2series.startIonNumber = 2;
a2series.endIonNumber = 2;
a2series.startMass = 0.1;
a2series.endMass = -0.1;
//No rule for number of modifications.
a2series.startMods2 = 0;
a2series.endMods2 = 999;
a2series.useModSeqRule = false;
//Changed PM_FRAGMENTDISPLAY 2008-05-18
a2series.yDisplayLevel4 = 0; //As B-ions. //1
a2series.yDisplayLevelForMatching4 = 4; //As B-ions.
anInOutIonTables.Add(a2series);
}
} //addA2ionSeries().
//****************************************************************************
//* SUBROUTINE NAME: addYionsWithPhosLoss
//d$ <summary>Add definition for common ion-series: y-ions with some
// number of phos loss and a certain charge. </summary>
//
//****************************************************************************
private static void addYionsWithPhosLoss(
ref List<singleIonSeriesStructure> anInOutIonTables,
int anIonSeriesID,
int aCharge3,
int aPhosLosses2
)
{
//Single charged y-ions with phos-loss.
singleIonSeriesStructure YphosSeries;
//Changed PM_REFACTOR 2008-06-23
//YphosSeries.ionSeriesID = 5001 + xyz; -variable!
YphosSeries.ionSeriesID2 = anIonSeriesID;
int basePhos = 98;
int nomimalMassLoss = basePhos * aPhosLosses2;
string nomimalMassLossStr = nomimalMassLoss.ToString();
YphosSeries.ionSeriesName =
chargeWord(aCharge3) + " full y series with " +
nomimalMassLossStr + " Da loss.";
YphosSeries.shortName2 = "y";
YphosSeries.postFix = "-" + nomimalMassLossStr;
//Later: use constant or similar...
YphosSeries.offsetFromResidueToNeutral =
////aPhosLosses2 * -79.96633093 //Phos80, -98+18, -Phos98 + water
//+18.0105647 - aPhosLosses2 * 97.97689563
//aPhosLosses2 * -18.0105647; //We don't know anything (about phos and such - we just marked something that 98 Da lower, wether it is phosporylated or not).
//aPhosLosses2 * -18.0105647 //No phos anywhere when it has been lost!!!!
//0.0 //!!!! - only true if the site is NOT phosphorylated.
//This is to get -98 or -196 with respect to the standard y-series.
//-80 for one loss is +18-98 = -80. 18 is the offset for standard y.
//-178 for two losses is +18-196 = -178. 18 is the offset for standard y.
+18.0105647 - aPhosLosses2 * 97.97689563
;
YphosSeries.forward = false;
YphosSeries.colour = 419;
YphosSeries.isPrecursorDerived = false;
YphosSeries.charge = aCharge3;
YphosSeries.startIonNumber = 1;
YphosSeries.endIonNumber = -1 - 1; //Not yN.
YphosSeries.startMass = 0.1;
YphosSeries.endMass = -0.1;
//At least one, but that should already be coverered by matching
//the phos modification.
YphosSeries.startMods2 = aPhosLosses2;
YphosSeries.endMods2 = 999;
YphosSeries.useModSeqRule = true;
//Changed PM_NEW_DISPLAYLEVEL_ION_SERIES 2008-05-26
int matchLevel=0;
if (aCharge3 == 1)
{
matchLevel = 3;
}
else
{
if (aPhosLosses2 == 1)
{
matchLevel = 1;
}
}
//Changed PM_FRAGMENTDISPLAY 2008-05-18
YphosSeries.yDisplayLevel4 = 0;
//Changed PM_NEW_DISPLAYLEVEL_ION_SERIES 2008-05-26
//YphosSeries.yDisplayLevelForMatching4 = 3;
YphosSeries.yDisplayLevelForMatching4 = matchLevel;
anInOutIonTables.Add(YphosSeries);
} //addYionsWithPhosLoss()
//****************************************************************************
//* SUBROUTINE NAME: addBionsWithPhosLoss
//d$ <summary>Add definition for common ion-series: y-ions with some
// number of phos loss and a certain charge. </summary>
//
//****************************************************************************
private static void addBionsWithPhosLoss(
ref List<singleIonSeriesStructure> anInOutIonTables,
int anIonSeriesID,
int aCharge3,
int aPhosLosses2
)
{
//Single charged b-ions with phos-loss.
singleIonSeriesStructure BphosSeries;
//Changed PM_REFACTOR 2008-06-23
//BphosSeries.ionSeriesID = 5101 + xyz; -variable! ;
BphosSeries.ionSeriesID2 = anIonSeriesID;
int basePhos = 98;
int nomimalMassLoss = basePhos * aPhosLosses2;
string nomimalMassLossStr = nomimalMassLoss.ToString();
BphosSeries.ionSeriesName =
chargeWord(aCharge3) + " full b series with " +
nomimalMassLossStr + " Da loss.";
BphosSeries.shortName2 = "b";
BphosSeries.postFix = "-" + nomimalMassLossStr;
//Later: use constant or similar...
BphosSeries.offsetFromResidueToNeutral =
////aPhosLosses2 * -79.96633093 //Phos80, -98+18, -Phos98 + water
//aPhosLosses2 * -18.0105647 //No phos anywhere when it has been lost!!!!
//This is to get -98 or -196 with respect to the standard b-series.
//-98 for one loss is +0-98 = -98. 0 is the offset for standard b.
//-196 for two losses is +0-196 = -196. 0 is the offset for standard b.
-aPhosLosses2 * 97.97689563
;
BphosSeries.forward = true;
BphosSeries.colour = 421;
BphosSeries.isPrecursorDerived = false;
BphosSeries.charge = aCharge3;
BphosSeries.startIonNumber = 1;
BphosSeries.endIonNumber = -1 - 1; //Not bN.
BphosSeries.startMass = 0.1;
BphosSeries.endMass = -0.1;
//At least one, but that should already be coverered by matching
//the phos modification.
BphosSeries.startMods2 = aPhosLosses2;
BphosSeries.endMods2 = 999;
BphosSeries.useModSeqRule = true;
//Changed PM_NEW_DISPLAYLEVEL_ION_SERIES 2008-05-26
int matchLevel=0;
if (aCharge3 == 1)
{
matchLevel = 2;
}
//Changed PM_FRAGMENTDISPLAY 2008-05-18
BphosSeries.yDisplayLevel4 = 0;
//Changed PM_NEW_DISPLAYLEVEL_ION_SERIES 2008-05-26
//BphosSeries.yDisplayLevelForMatching4 = 3-1;
BphosSeries.yDisplayLevelForMatching4 = matchLevel;
anInOutIonTables.Add(BphosSeries);
} //addBionsWithPhosLoss()
//****************************************************************************
//* SUBROUTINE NAME: addPrecursor
//d$ <summary>Add definition for precursor; with some
// number of phos losses and a certain charge. </summary>
//
//****************************************************************************
private static void addPrecursor(
ref List<singleIonSeriesStructure> anInOutIonTables,
int anIonSeriesID,
int aCharge3,
int aPhosLosses2
)
{
//Charged precursor with possible phos-loss.
singleIonSeriesStructure precursor;
//Changed PM_REFACTOR 2008-06-23
//precursor.ionSeriesID = 7001 + xyz; -variable
precursor.ionSeriesID2 = anIonSeriesID;
int basePhos = 98;
int nomimalMassLoss = basePhos * aPhosLosses2;
string nomimalMassLossStr = nomimalMassLoss.ToString();
precursor.ionSeriesName =
chargeWord(aCharge3) + " precursor with " +
nomimalMassLossStr + " Da loss.";
precursor.shortName2 = "prec";
if (aPhosLosses2 == 0)
{
precursor.postFix = "";
}
else
{
precursor.postFix = "-" + nomimalMassLossStr;
}
//Later: use constant or similar...
precursor.offsetFromResidueToNeutral =
+18.0105647 - aPhosLosses2 * 97.97689563
;
precursor.forward = false; //As we use yN - it has the
// same mass as the precursor.
precursor.colour = 433;
precursor.isPrecursorDerived = true;
precursor.charge = aCharge3;
//yN.
precursor.startIonNumber = -1;
precursor.endIonNumber = -1;
precursor.startMass = 0.1;
precursor.endMass = -0.1;
precursor.startMods2 = 0;
precursor.endMods2 = 999;
precursor.useModSeqRule = false;
//Changed PM_FRAGMENTDISPLAY 2008-05-18
precursor.yDisplayLevel4 = 0;
precursor.yDisplayLevelForMatching4 = 2;
anInOutIonTables.Add(precursor);
} //addPrecursor()
//****************************************************************************
//* SUBROUTINE NAME: addChargedLittleZionSeries
//d$ <summary>Add definition for common ion-series: z-ions</summary>
//
//****************************************************************************
private static void addChargedLittleZionSeries(
ref List<singleIonSeriesStructure> anInOutIonTables,
int anIonSeriesID,
int aCharge2
)
{
{ //Single charged z-ions.
singleIonSeriesStructure fullZseries;
fullZseries.ionSeriesID2 = anIonSeriesID;
fullZseries.ionSeriesName =
chargeWord(aCharge2) + " full z series.";
fullZseries.shortName2 = "z";
fullZseries.postFix = "";
fullZseries.offsetFromResidueToNeutral =
MSconstants.NORMAL_C_TERMINUS_MONO +
MSconstants.NORMAL_N_TERMINUS_MONO -
(MSconstants.N_MASS_MONO +
2 * MSconstants.HYDROGEN_MASS)
; //+2 Da. H20 - NH2 = O - N
fullZseries.forward = false;
fullZseries.colour = 419;
fullZseries.isPrecursorDerived = false;
fullZseries.charge = aCharge2;
fullZseries.startIonNumber = 1 + 0; //Start with z1.
fullZseries.endIonNumber = -1 - 1; //Not zN.
fullZseries.startMass = 0.1;
fullZseries.endMass = -0.1;
//No rule for number of modifications.
fullZseries.startMods2 = 0;
fullZseries.endMods2 = 999;
fullZseries.useModSeqRule = false;
fullZseries.yDisplayLevel4 = 0; //2-1
fullZseries.yDisplayLevelForMatching4 = 4;
anInOutIonTables.Add(fullZseries);
}
} //addChargedLittleZionSeries().
//****************************************************************************
//* SUBROUTINE NAME: addChargedCionSeries
//d$ <summary>Add definition for common ion-series: c-ions</summary>
//
//****************************************************************************
private static void addChargedCionSeries(
ref List<singleIonSeriesStructure> anInOutIonTables,
int anIonSeriesID,
int aCharge2
)
{
{ //Single charged c-ions.
singleIonSeriesStructure fullCseries;
fullCseries.ionSeriesID2 = anIonSeriesID;
fullCseries.ionSeriesName =
chargeWord(aCharge2) + " full c series.";
fullCseries.shortName2 = "c";
fullCseries.postFix = "";
fullCseries.offsetFromResidueToNeutral =
MSconstants.N_MASS_MONO +
3 * MSconstants.HYDROGEN_MASS
; //+17 Da, NH3.
fullCseries.forward = true;
fullCseries.colour = 421;
fullCseries.isPrecursorDerived = false;
fullCseries.charge = aCharge2;
fullCseries.startIonNumber = 1 + 0; //Start with c1.
fullCseries.endIonNumber = -1 - 1; //Not cN.
fullCseries.startMass = 0.1;
fullCseries.endMass = -0.1;
//No rule for number of modifications.
fullCseries.startMods2 = 0;
fullCseries.endMods2 = 999;
fullCseries.useModSeqRule = false;
fullCseries.yDisplayLevel4 = 0; //2-1
fullCseries.yDisplayLevelForMatching4 = 4;
anInOutIonTables.Add(fullCseries);
}
} //addChargedCionSeries().
//****************************************************************************
//* SUBROUTINE NAME: addChargedBigZionSeries
//d$ <summary>Add definition for common ion-series: Z-ions</summary>
//
//****************************************************************************
private static void addChargedBigZionSeries(
ref List<singleIonSeriesStructure> anInOutIonTables,
int anIonSeriesID,
int aCharge2
)
{
{ //Single charged z-ions.
singleIonSeriesStructure fullZseries;
fullZseries.ionSeriesID2 = anIonSeriesID;
fullZseries.ionSeriesName =
chargeWord(aCharge2) + " full Z series.";
fullZseries.shortName2 = "Z_H";
fullZseries.postFix = "";
fullZseries.offsetFromResidueToNeutral =
MSconstants.NORMAL_C_TERMINUS_MONO +
MSconstants.NORMAL_N_TERMINUS_MONO -
(MSconstants.N_MASS_MONO +
2 * MSconstants.HYDROGEN_MASS) +
MSconstants.HYDROGEN_MASS //
; //+2 Da. H20 - NH2 + H = O - N + H
fullZseries.forward = false;
fullZseries.colour = 431; //For z: 419
fullZseries.isPrecursorDerived = false;
fullZseries.charge = aCharge2;
fullZseries.startIonNumber = 1 + 0; //Start with z1.
fullZseries.endIonNumber = -1 - 1; //Not zN.
fullZseries.startMass = 0.1;
fullZseries.endMass = -0.1;
//No rule for number of modifications.
fullZseries.startMods2 = 0;
fullZseries.endMods2 = 999;
fullZseries.useModSeqRule = false;
fullZseries.yDisplayLevel4 = 0; //2-1
fullZseries.yDisplayLevelForMatching4 = 3;
anInOutIonTables.Add(fullZseries);
}
} //addChargedBigZionSeries().
//****************************************************************************
//* SUBROUTINE NAME: defaultIonTables
//d$ <summary>Returns the default set of ions series tables</summary>
//
//****************************************************************************
public static ionDefinitionsStructure defaultIonTables()
{
//Changed PM_REFACTOR 2008-10-09. We now again return values instead
// of using output parameters.
//Old parameters:
// out List<ionSeriesTableStructure> anOutIonTables,
// out List<singleIonSeriesStructure> anOutSingleIonSeries)
//Changed PM_REFACTOR 2008-10-09 (renaming, par -> local)
List<ionSeriesTableStructure> outIonTables =
new List<ionSeriesTableStructure>();
//Changed PM_REFACTOR 2008-10-09 (renaming, par -> local)
//Changed PM_REFACTOR 2008-06-23
List<singleIonSeriesStructure> outSingleIonSeries =
new List<singleIonSeriesStructure>();
//Changed PM_MARKER 2008-06-23
//
//Reduce redundancy here and even more in XML file by splitting into
//two levels: simple ion series and higher level with rules, etc.
//
//The simple ion series are referred to by an ID (integer), like for
//quantitation modes/ modifications.
//Changed PM_REFACTOR 2008-06-23
//Single ion series defition (lower level in the new two
//level defintion.)
//
//Note: this does ***not*** constitute an ion table. It is
// just a list of ion series; with a unique ID for
// each ion series. Below we then refer to some ion
// series by the unique ID. In this way we avoid
// redundant definitions of ion-series.
{
addSingleChargedYionSeries( ref outSingleIonSeries, 1201);
addDoubleChargedYionSeries( ref outSingleIonSeries, 1210, 700.0);
addSingleChargedBionSeries( ref outSingleIonSeries, 2001);
addA2ionSeries( ref outSingleIonSeries, 3001);
addYionsWithPhosLoss(ref outSingleIonSeries, 5001, 1, 1);
addYionsWithPhosLoss(ref outSingleIonSeries, 5002, 2, 1);
addBionsWithPhosLoss(ref outSingleIonSeries, 5101, 1, 1);
addBionsWithPhosLoss(ref outSingleIonSeries, 5102, 2, 1);
addYionsWithPhosLoss(ref outSingleIonSeries, 5003, 1, 2);
addYionsWithPhosLoss(ref outSingleIonSeries, 5004, 2, 2);
addBionsWithPhosLoss(ref outSingleIonSeries, 5103, 1, 2);
addBionsWithPhosLoss(ref outSingleIonSeries, 5104, 2, 2);
addPrecursor(ref outSingleIonSeries, 7001, 2, 0);
addPrecursor(ref outSingleIonSeries, 7002, 2, 1);
addPrecursor(ref outSingleIonSeries, 7003, 1, 1);
//Changed PM_ETD_SUPPORT 2008-06-24. Single charged...
addChargedLittleZionSeries(ref outSingleIonSeries, 8001, 1);
addChargedCionSeries(ref outSingleIonSeries, 8501, 1);
addChargedBigZionSeries(ref outSingleIonSeries, 8011, 1);
//Double charged...
addChargedLittleZionSeries(ref outSingleIonSeries, 8002, 2);
addChargedCionSeries(ref outSingleIonSeries, 8502, 2);
addChargedBigZionSeries(ref outSingleIonSeries, 8012, 2);
}
{ //Normal ion series plus phos losses for S and T phophorylations.
ionSeriesTableStructure someionSeriesTable;
someionSeriesTable.ionTableID = 3410;
someionSeriesTable.ionTableName =
AppConstants.SHORT_APP +
" classic - plus phos losses for Serine phophorylations";
someionSeriesTable.rules2 = new List<matchRuleStructure>();
someionSeriesTable.ionSeries2 = new List<int>();
matchRuleStructure rule3;
//rule2.matchModID = 5045; //"Oxidation (M)". Mox.
//rule2.matchModID = 5051; //"phospho(STY)". E.g. Cell paper data.
rule3.matchModID = 5048; //"Phospho (ST)"
//Changed PM_MARKER_SPECTRUMCLASSIFICATION 2008-06-23
//Add rules for spectrum classification, e.g. spectrum
//must be ETD.
//Changed PM_MARKER_PRECURSORCHARGE_SPECIFICATION 2008-06-23
//Add precursor charge rules, e.g. equal to precursor, or one less...
//Not yet.
//rule2.minMods = 1;
//rule2.maxMods = 99;
//Changed PM_GENERALISED_IONSERIES_SPECTRUMCLASSIFICATION 2008-06-24
rule3.MSMSspectrumClassification =
spectrumSubTypeEnum.enumIsFragmentCID;
someionSeriesTable.rules2.Add(rule3);
//Changed PM_MS3_PHOSLOSS_FRAGMENTS 2008-07-23. Now also match
//in MS3 spectra, in addition to normal MS2.
rule3.MSMSspectrumClassification =
spectrumSubTypeEnum.enumIsFragmentMS3;
someionSeriesTable.rules2.Add(rule3);
//Add check for uniqueness of ID (refs added to ionSeries2 below)???
//Add check for exisistence. This could work here to detect
//internal problems in the code and when reading in from the XML file
//(e.g. pass a hash that the functions can use to check
//uniqueness of ID.)
//Changed PM_REFACTOR 2008-06-23
// addSingleChargedYionSeries(ref someionSeriesTable.ionSeries);
// addDoubleChargedYionSeries(ref someionSeriesTable.ionSeries, 700.0);
//
// addSingleChargedBionSeries(ref someionSeriesTable.ionSeries);
// addA2ionSeries(ref someionSeriesTable.ionSeries);
//
// //Precursor, various versions.
// addPrecursor(ref someionSeriesTable.ionSeries, 2, 0);
// addPrecursor(ref someionSeriesTable.ionSeries, 2, 1);
// addPrecursor(ref someionSeriesTable.ionSeries, 1, 1);
someionSeriesTable.ionSeries2.Add(1201); //y single
someionSeriesTable.ionSeries2.Add(1210); //y double
someionSeriesTable.ionSeries2.Add(2001); //b single
someionSeriesTable.ionSeries2.Add(3001); //a2
someionSeriesTable.ionSeries2.Add(7001); //Precursor, double
// charge - only suitable for triple charged precursor??
someionSeriesTable.ionSeries2.Add(7002); //Precursor, double
// charge, one phos loss - only suitable for triple charged precursor??
someionSeriesTable.ionSeries2.Add(7003); //Precursor, single
// charge, one phos loss - suitable for what??
//Changed PM_REFACTOR 2008-06-23
// //Single phos loss
// addYionsWithPhosLoss(ref someionSeriesTable.ionSeries, 1, 1);
// addYionsWithPhosLoss(ref someionSeriesTable.ionSeries, 2, 1);
// addBionsWithPhosLoss(ref someionSeriesTable.ionSeries, 1, 1);
// addBionsWithPhosLoss(ref someionSeriesTable.ionSeries, 2, 1);
//
// //Double phos loss
// addYionsWithPhosLoss(ref someionSeriesTable.ionSeries, 1, 2);
// addYionsWithPhosLoss(ref someionSeriesTable.ionSeries, 2, 2);
// addBionsWithPhosLoss(ref someionSeriesTable.ionSeries, 1, 2);
// addBionsWithPhosLoss(ref someionSeriesTable.ionSeries, 2, 2);
someionSeriesTable.ionSeries2.Add(5001); //y single, one phos loss.
someionSeriesTable.ionSeries2.Add(5002); //y double, one phos loss.
someionSeriesTable.ionSeries2.Add(5101); //b single, one phos loss.
someionSeriesTable.ionSeries2.Add(5102); //b double, one phos loss.
someionSeriesTable.ionSeries2.Add(5003); //y single, double phos loss.
someionSeriesTable.ionSeries2.Add(5004); //y double, double phos loss.
someionSeriesTable.ionSeries2.Add(5103); //b single, double phos loss.
someionSeriesTable.ionSeries2.Add(5104); //b double, double phos loss.
outIonTables.Add(someionSeriesTable);
} //Block. Normal ion series + phos losses for Serine phophorylations.
{ //For ECD/ETD, c/z ion series table.
ionSeriesTableStructure someionSeriesTable;
someionSeriesTable.ionTableID = 3600;
someionSeriesTable.ionTableName = "ETD/ECD";
someionSeriesTable.rules2 = new List<matchRuleStructure>();
someionSeriesTable.ionSeries2 = new List<int>();
matchRuleStructure rule1;
rule1.matchModID = -1; //Match anything. Thus this table
// should be added last (until we sort by some match order field).
//Not yet.
//rule1.minMods = 1; //Just in case.
//rule1.maxMods = 99; //Just in case.
//Changed PM_GENERALISED_IONSERIES_SPECTRUMCLASSIFICATION 2008-06-24
rule1.MSMSspectrumClassification =
spectrumSubTypeEnum.enumIsFragmentECD;
someionSeriesTable.rules2.Add(rule1);
someionSeriesTable.ionSeries2.Add(8001); //z single
someionSeriesTable.ionSeries2.Add(8501); //c single
someionSeriesTable.ionSeries2.Add(8002); //z double
someionSeriesTable.ionSeries2.Add(8502); //c double
someionSeriesTable.ionSeries2.Add(8011); //Z single
someionSeriesTable.ionSeries2.Add(8012); //Z double
outIonTables.Add(someionSeriesTable);
} //Block. ECD/ETD ion series: c, z.
{ //Normal ion series table, as in older versions of the application.
ionSeriesTableStructure someionSeriesTable;
someionSeriesTable.ionTableID = 3400;
someionSeriesTable.ionTableName =
AppConstants.SHORT_APP + " classic";
someionSeriesTable.rules2 = new List<matchRuleStructure>();
someionSeriesTable.ionSeries2 = new List<int>();
matchRuleStructure rule1;
rule1.matchModID = -1; //Match anything. Thus this table
// should be added last (until we sort by some match order field).
//Not yet.
//rule1.minMods = 1; //Just in case.
//rule1.maxMods = 99; //Just in case.
//Changed PM_GENERALISED_IONSERIES_SPECTRUMCLASSIFICATION 2008-06-24
rule1.MSMSspectrumClassification =
spectrumSubTypeEnum.enumIsFragmentCID;
someionSeriesTable.rules2.Add(rule1);
//Changed PM_MS3_DISPLAY_BROKEN 2008-07-22. Symptom was
// NullReferenceException, "Problem opening the raw data
// file (wiff, raw or idx). Likely reasons: ..."
rule1.MSMSspectrumClassification =
spectrumSubTypeEnum.enumIsFragmentMS3;
someionSeriesTable.rules2.Add(rule1);
//Changed PM_REFACTOR 2008-06-23
// addSingleChargedYionSeries(ref someionSeriesTable.ionSeries);
// addDoubleChargedYionSeries(ref someionSeriesTable.ionSeries, 700.0);
// addSingleChargedBionSeries(ref someionSeriesTable.ionSeries);
// addA2ionSeries(ref someionSeriesTable.ionSeries);
someionSeriesTable.ionSeries2.Add(1201); //y single
someionSeriesTable.ionSeries2.Add(1210); //y double
someionSeriesTable.ionSeries2.Add(2001); //b single
someionSeriesTable.ionSeries2.Add(3001); //a2
outIonTables.Add(someionSeriesTable);
} //Block. Standard ion series: a2, b, y, y++ less than 700 Da.
//Changed PM_REFACTOR 2008-10-09
ionDefinitionsStructure toReturn;
toReturn.ionTables = outIonTables;
toReturn.singleIonSeries = outSingleIonSeries;
return toReturn;
} //defaultIonTables()
/****************************************************************************
* <placeholder for header> *
****************************************************************************/
private void extractModInfo(int aModID)
{
quantModificationStructure modInfo =
mQuantObject.getModification(aModID);
Dictionary<string, int> AAhash = new Dictionary<string, int>();
//This code is probably also somewhere else!!!! Do refactor when
//we find it...
//Flatten specification with respect to affected amino acids.
foreach (AAsetStruct someAAset in modInfo.affectedAAs)
{
string AAs = someAAset.AAs;
int len = AAs.Length;
for (int i = 0; i < len; i++)
{
string AA = AAs.Substring( i, 1);
int count;
if ( AAhash.TryGetValue(AA,out count))
{
//We have already seen the amino acid before. This is
//unexpected. Should we issue some kind of error
//message or warning?
count++;
AAhash[AA] = count;
}
else
{
AAhash.Add(AA, 1);
}
}
} //Through modInfo.affectedAAs
int len2 = AAhash.Count;
List<string> AAlist = new List<string>(len2);
Dictionary<string, int>.Enumerator hashEnumerator2 =
AAhash.GetEnumerator();
while (hashEnumerator2.MoveNext())
{
string curKey = hashEnumerator2.Current.Key;
int curValue = hashEnumerator2.Current.Value;
AAlist.Add(curKey);
} //Hash iteration.
mModHash.Add(aModID, AAlist);
} //extractModInfo
/****************************************************************************
* <placeholder for header> *
****************************************************************************/
private bool modInSequence(
ref List<string> aParticularModAAs,
ref string anInAAsequence,
bool aUseSeqRule,
int aMinimumCountInFragmentSequence)
{
bool doAdd = true;
if (aParticularModAAs != null &&
aUseSeqRule == true)
{
//Fragment amino acids must contain at least
//one of the amino acids that the
//modification affects.
bool AAaffectedinFragment = false;
foreach (string someAAbyMod in aParticularModAAs)
{
int countForOneModAA = 0;
int searchIndex = 0;
//This search is an
bool end = false;
while ( ! end)
{
int idx = anInAAsequence.IndexOf(someAAbyMod, searchIndex);
if (idx < 0)
{
end = true;
}
else
{
countForOneModAA++;
if (countForOneModAA >= aMinimumCountInFragmentSequence)
{
AAaffectedinFragment = true;
end = true; //No need to continue. Fragment amino
// acid sequence contains enough amino acids that
// are affected by the modification that made
// a match for an ion table.
}
else
{
//Prepare for searching on.
searchIndex = idx + 1; //Jump over the single matched AA.
}
}
}
} //Through aParticularModAAs
doAdd = AAaffectedinFragment;
} //Mod AAs in effect.
else
{
int peter2 = 2;
}
//For breakpoints.
if (aUseSeqRule)
{
int peter2 = 2;
}
else
{
int peter3 = 3;
}
return doAdd;
} //modInSequence()
//Changed PM_REFACTOR 2008-06-23
//****************************************************************************
//* SUBROUTINE NAME: getIonSeriesDef *
//d$ <summary>XYZ</summary>
//
//****************************************************************************
private static singleIonSeriesStructure getIonSeriesDef(
int anIonSeriesDefID, ref List<singleIonSeriesStructure> aSingleIonSeries)
{
//Detect if it does not exist... If it happens we can say that this
//condition should have been detected earlier by the program, e.g.
//when the XML settings file was read...
bool found = false;
singleIonSeriesStructure toReturn;
//Keep compiler happy...
toReturn.ionSeriesName = null;
toReturn.postFix = null;
toReturn.shortName2 = null;
toReturn.charge = -1;
toReturn.colour = -1;
toReturn.endIonNumber = -1;
toReturn.endMass = -1.0;
toReturn.endMods2 = -1;
toReturn.forward = false;
toReturn.ionSeriesID2 = -1;
toReturn.isPrecursorDerived = false;
toReturn.offsetFromResidueToNeutral = -1.0;
toReturn.startIonNumber = -1;
toReturn.startMass = -1.0;
toReturn.startMods2 = -1;
toReturn.useModSeqRule = false;
toReturn.yDisplayLevel4 = -1;
toReturn.yDisplayLevelForMatching4 = -1;
//Linear search, but we have an the order of 10 elements.
foreach (singleIonSeriesStructure someSingleIonSeries in aSingleIonSeries)
{
if (someSingleIonSeries.ionSeriesID2 == anIonSeriesDefID)
{
found = true;
toReturn = someSingleIonSeries;
break;
}
} //Through set of defined single ion series.
if (!found)
{
string msgStr =
"The ion series with ID " + anIonSeriesDefID +
" could not be found. It does not exist in definitions of the " +
"set of ion series (defined in an XML settings file). Edit this " +
"file as appropriate or delete the file to let the program " +
"create a new version with default content.";
System.Windows.Forms.MessageBox.Show(msgStr);
}
return toReturn;
} //getIonSeriesDef
//****************************************************************************
//* SUBROUTINE NAME: computeFragments *
//d$ <summary>XYZ</summary>
//
//****************************************************************************
public List<fragmentExStructure> computeFragments(
ref string anInPeptideSequence,
ref List<double> anInYarray,
ref List<double> anInBarray,
ref List<List<AAsetStruct>> anInModificationsDefsList,
ionSetStruct anInMassAdjustments,
ref List<modificationCountStruct> anInModHits,
spectrumSubTypeEnum anInMSMStype
)
{
//Later: mass adjustments. Just refactor
// from CalcFragIons() (file peptideFragments.vb),
// block "If useMassAdjustment Then".
Trace.Assert(
anInMSMStype != spectrumSubTypeEnum.enumIsNormalMS &&
anInMSMStype != spectrumSubTypeEnum.enumIsZoomMS,
"PIL ASSERT. Spectrum type, " + anInMSMStype.ToString() +
", for finding a set of ion series is a precursor spectrum type " +
"and not a fragment " +
"spectrum type. This can happen if the Mascot result file has " +
"not been associated with the correct raw spectrum file.");
List<fragmentExStructure> toReturn =
new List<fragmentExStructure>(10);
int particularModID = -1; //Will become positive if we match
// a particular ion table due to a particular peptide modification.
//matchRuleStructure matchedRule;
int modsForMatched = -1;
//First find which ion table to use... It depends on some rules, e.g.
//if the peptide has a Phospho ST modification.
ionSeriesTableStructure ionTableToUse;
ionTableToUse.ionSeries2 = null; //Keep compiler happy.
ionTableToUse.rules2 = null; //Keep compiler happy.
foreach (ionSeriesTableStructure someIonTable in mIonDefs.ionTables)
{
bool matchedThisTable = false;
//Go through the rules. We use the first that match.
//
//Add ASSERT that check we always match something? (to avoid
//using an empty set of ions - no ions!)
foreach (matchRuleStructure someRule in someIonTable.rules2)
{
bool matchedMod = true;
bool matchedSpectrumType = true;
if (someRule.matchModID >= 0)
{
matchedMod = false;
if (anInModHits != null) //Is peptide modified?
{
foreach (modificationCountStruct someModHit in anInModHits)
{
//As we go through the peptide's modification: use
//the opportunity to cache information about
//defined modifications. We need it later in
//this function.
int modID = someModHit.quantModificationID;
List<string> someInfo;
if (!mModHash.TryGetValue(modID, out someInfo))
{
extractModInfo(modID);
}
if (modID == someRule.matchModID)
{
int modHits = someModHit.count3;
particularModID = modID;
modsForMatched = modHits;
//Use number of modifications as a
//filter, someRule.minMods and someRule.maxMods
//Those two fields should also be initialised.
//Not yet.
//if (modHits >= someRule.minMods &&
// modHits <= someRule.maxMods)
//{
// //Not yet.
//}
matchedMod = true;
}
} //Through peptide modifications.
}
else
{
int peter2 = 2; //No modifications in peptide. Let
// us hope we have a rule that always match. Otherwise
// we get no ions...
}
} //Modification rule specified.
else
{
int peter7 = 7; //For breakpoints. Modification rule
// not specified.
}
//What is this check for? Answer: this is for our second
//kind of rules; MS/MS type. E.g. one kind of fragments
//for ECD, another for MS2 CID, a third for MS3.
if (someRule.MSMSspectrumClassification !=
spectrumSubTypeEnum.enumST_DoesNotApply)
{
matchedSpectrumType = false;
if (someRule.MSMSspectrumClassification == anInMSMStype)
{
matchedSpectrumType = true;
}
else
{
int peter9 = 9; //For breakpoints. Modification rule
// did not match.
}
}
else
{
int peter8 = 8; //For breakpoints. Spectrum type
// not specified.
}
if (matchedMod && matchedSpectrumType)
{
matchedThisTable = true;
break; //No need to continue.
}
} //Through rules.
if ( matchedThisTable)
{
ionTableToUse = someIonTable;
break;
}
else
{
int peter2 = 2; //For breakpoints. Did not match any
// rules. Try next ion table.
}
} //Through mIonTables, finding a particular ion table (with some set
//of ion series).
int plen = anInPeptideSequence.Length;
fragmentExStructure someFragmentItem; //Scratch.
{ //Block.
someFragmentItem.ionMatched = false; //Just in case.
} //Block.
List<string> particularModAAs = null; //Flag if should be used or not.
if (particularModID >= 0)
{
//This means a particular ion table was matched due to a
//particular peptide modification, e.g. a phosphorylation.
particularModAAs = mModHash[particularModID];
}
//Next: go through the different defined ion series in turn.
//Fired because no rules were specified for MS3 spectra...
//Symptom before the assert (exception because ionTableToUse.ionSeries2
//was null): "Problem opening the raw data file (wiff, raw or
//idx). Likely reasons: ...".
Trace.Assert(
ionTableToUse.ionSeries2 != null,
"PIL ASSERT. ionTableToUse.ionSeries2 is null.");
//Changed PM_REFACTOR 2008-06-23
// foreach ( singleIonSeriesStructure someIonSeriesDef in
// ionTableToUse.ionSeries)
foreach (int someIonSeriesDefID in ionTableToUse.ionSeries2)
{
//Perhaps later: cache result of this lookup. To save on the
// memory cost of keeping the compiler happy.
singleIonSeriesStructure someIonSeriesDef =
getIonSeriesDef(
someIonSeriesDefID, ref mIonDefs.singleIonSeries);
bool doUseIonSeries = true;
if (modsForMatched >= 0) //Is negative if no rule was
//matched - e.g. using a default rule.
{
if (modsForMatched < someIonSeriesDef.startMods2 ||
modsForMatched > someIonSeriesDef.endMods2)
{
doUseIonSeries = false; //E.g. y-198 series is not computed
// if modifications for matching pST is 1.
}
}
if (doUseIonSeries)
{
bool useModSeqRule = someIonSeriesDef.useModSeqRule;
//Common setup (for backward and forward ion series).
int startIonNumber0;
int endIonNumber0;
string shortName = someIonSeriesDef.shortName2;
string postFix = someIonSeriesDef.postFix;
int charge = someIonSeriesDef.charge;
int chargeIndex0 = charge - 1;
bool outputIonNumber = ! someIonSeriesDef.isPrecursorDerived;
double startMass = someIonSeriesDef.startMass;
if (startMass < 0.0)
{
//Later: actual difference from precursor.
startMass = 333333.3;
}
double endMass = someIonSeriesDef.endMass;
if (endMass < 0.0)
{
//Later: actual difference from precursor.
endMass = 333333.3;
}
double massOffset = someIonSeriesDef.offsetFromResidueToNeutral;
{
bool allPositions;
int maxMods;
PILpeptide.findPositionsEtc(
someIonSeriesDef.startIonNumber,
someIonSeriesDef.endIonNumber, plen,
out allPositions,
out startIonNumber0, out endIonNumber0, out maxMods);
//Translation to old datastructure.
someFragmentItem.charge = someIonSeriesDef.charge;
ionTypeEnum ionType = ionTypeEnum.enumPrecursorIon2;
//Changed PM_MATCH_PRECURSOR 2008-05-20
////For now.
//if (!someIonSeriesDef.isPrecursorDerived)
if (someIonSeriesDef.isPrecursorDerived)
{
int peter3 = 3;
}
else
{
int peter4 = 4;
}
if (true)
{
//Later: case on "someIonSeriesDef.colour"
//Changed PM_GENERALISED_IONSERIES 2008-05-12
switch (someIonSeriesDef.colour)
{
case 419: //y
ionType = ionTypeEnum.enumYion2;
break;
case 421: //b
ionType = ionTypeEnum.enumBion2;
break;
case 431: //a
ionType = ionTypeEnum.enumAion2;
break;
//Changed PM_MATCH_PRECURSOR 2008-05-20
case 433: //Precursor
//Disguise as y, so it is matched.
ionType = ionTypeEnum.enumYion2;
break;
default:
Trace.Assert(
false, "PIL ASSERT. Select Case never fall-through");
break;
}
}
someFragmentItem.ionType = ionType;
someFragmentItem.ionMatched = false; //Reset every time. Just
// in case.
//Changed PM_FRAGMENTDISPLAY 2008-05-18
someFragmentItem.yDisplayLevel2 =
someIonSeriesDef.yDisplayLevel4;
someFragmentItem.yDisplayLevelForMatching2 =
someIonSeriesDef.yDisplayLevelForMatching4;
//Shift all series one up. For the default ion
//series set this means e.g. y++ series is in
//the x-axis area of the spectrum.
int shiftUpCount = 1;
someFragmentItem.yDisplayLevel2 -= shiftUpCount;
someFragmentItem.yDisplayLevelForMatching2 -= shiftUpCount;
} //Block. Setting of common fields.
if (someIonSeriesDef.forward == true)
{
//Forwards series, e.g. b-ions.
//int len = mSequence.Length();
for (int i = startIonNumber0; i <= endIonNumber0; i++)
{
int indexOneBased = i + 1;
double bMass = anInBarray[i];
//Refactor this inner part?? It is almost identical
//to the backwards part.
//Later: combine B_ION_OFFSET and massOffset, outside loop.
double residueMass = bMass - MSconstants.B_ION_OFFSET;
double neutralFragmentMass = residueMass + massOffset;
if (neutralFragmentMass >= startMass &&
neutralFragmentMass <= endMass)
{
someFragmentItem.MCRcalcLoc =
PILmassCalc.chargeTransform(
neutralFragmentMass, 0, charge);
string chstr = mChargeStrings[chargeIndex0];
if (chstr.Length < 2)
{
//Only indicate charge for multiple charged.
chstr = "";
}
string ionNumberStr = "";
if (outputIonNumber)
{
ionNumberStr = indexOneBased.ToString();
}
someFragmentItem.descStr =
shortName +
chstr +
ionNumberStr +
postFix;
int idx1 = 0; //plen - 1 - i;
int len1 = indexOneBased; //Happens to be the case.
someFragmentItem.seq =
anInPeptideSequence.Substring(idx1, len1);
bool doAdd =
modInSequence(
ref particularModAAs,
ref someFragmentItem.seq,
useModSeqRule,
modsForMatched);
if (doAdd)
{
toReturn.Add(someFragmentItem);
}
else
{
int peter3 = 3; //For breakpoints.
}
} //Within specified mass range.
else
{
int peter2 = 2; //Outside mass range.
}
} //Through forward ion series
}
else
{
//Backwards series, e.g. y-ions.
//int len = mSequence.Length();
for (int i = startIonNumber0; i <= endIonNumber0; i++)
{
int indexOneBased = i + 1;
double yMass = anInYarray[i];
//Later: combine Y_ION_OFFSET and massOffset, outside loop.
double residueMass = yMass - MSconstants.Y_ION_OFFSET;
double neutralFragmentMass = residueMass + massOffset;
if (neutralFragmentMass >= startMass &&
neutralFragmentMass <= endMass)
{
someFragmentItem.MCRcalcLoc =
PILmassCalc.chargeTransform(
neutralFragmentMass, 0, charge);
string chstr = mChargeStrings[chargeIndex0];
if (chstr.Length < 2)
{
//Only indicate charge for multiple charged.
chstr = "";
}
string ionNumberStr = "";
if (outputIonNumber)
{
ionNumberStr = indexOneBased.ToString();
}
else
{
int peter2 = 2; //For breakpoints.
}
someFragmentItem.descStr =
shortName +
chstr +
ionNumberStr +
postFix;
//Later: proper frag sequence.
//someFragmentItem.seq=anInPeptideSequence.Substring(i,
//someFragmentItem.seq = "ACD";
int idx1 = plen - 1 - i;
int len1 = indexOneBased; //Happens to be the case.
someFragmentItem.seq =
anInPeptideSequence.Substring(idx1, len1);
//Check that the fragment sequence actually
// contains at least one amino acid that is
// affected by the modification (if the current
// ion series tables is matched by a modification).
bool doAdd =
modInSequence(
ref particularModAAs,
ref someFragmentItem.seq,
useModSeqRule,
modsForMatched);
if (doAdd)
{
toReturn.Add(someFragmentItem);
}
else
{
int peter3 = 3; //For breakpoints.
}
} //Within specified mass range.
else
{
int peter2 = 2; //Outside mass range.
}
} //Through backward ion series
} //else, for backwards series.
} //if doUseIonSeries
} //Through ionTableToUse.ionTables
return toReturn;
} //computeFragments()
//Changed PM_DTASC_COMPILE 2008-09-15. Moved here to remove
//other dependencies...
////Changed PM_DTASC_COMPILE 2008-02-11. Moved to here
//// from peptideFragments.vb. To remove difficult dependencies.
//****************************************************************************
//* <placeholder for header> *
//****************************************************************************
public static bool isForwardIon(ionTypeEnum anIonType)
{
bool toReturn = true;
switch (anIonType)
{
case ionTypeEnum.enumYion2:
toReturn = false;
break;
case ionTypeEnum.enumBion2:
break;
case ionTypeEnum.enumAion2:
break;
case ionTypeEnum.enumPrecursorIon2:
toReturn = false;
break;
default:
Trace.Assert(false, "PIL ASSERT. Select Case never fall-through");
break;
}
return toReturn;
} //isForwardIon()
} //class PILgeneralisedIonSeries
} //namespace massSpectrometryBase
Generated by script codePublish.pl at 2009-01-05T15:20:59.