/*
* Copyright 2006-2012 The MZmine 2 Development Team
*
* This file is part of MZmine 2.
*
* MZmine 2 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.
*
* MZmine 2 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
* MZmine 2; if not, write to the Free Software Foundation, Inc., 51 Franklin St,
* Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.sf.mzmine.util;
import java.util.HashMap;
import java.util.Vector;
import net.sf.mzmine.data.DataPoint;
import net.sf.mzmine.modules.peaklistmethods.identification.mascot.data.FragmentIon;
import net.sf.mzmine.modules.peaklistmethods.identification.mascot.data.FragmentIonType;
import net.sf.mzmine.modules.peaklistmethods.identification.mascot.data.ModificationPeptide;
import net.sf.mzmine.modules.peaklistmethods.identification.mascot.data.Peptide;
import net.sf.mzmine.modules.peaklistmethods.identification.mascot.data.PeptideFragmentation;
import net.sf.mzmine.modules.peaklistmethods.identification.mascot.data.PeptideIdentityDataFile;
import net.sf.mzmine.modules.peaklistmethods.identification.mascot.data.SerieIonType;
public class PeptideUtils {
/**
* This method calculates the start position of a possible H2O loss for the
* B-ion series. The returning variable is used for the H2O-loss
* fragmentions calculation. This variable holds the smallest index of
* S|T|E|D amino acid residue. These aminoacids can loose their H2O.
*
* @param String
* sequence
* @return int index.
*/
public static int getFirstBionLossH2O(String sequence) {
int indexBionLossH2O = sequence.length() - 1;
if (sequence.indexOf('S') != -1
&& sequence.indexOf('S') < indexBionLossH2O) {
indexBionLossH2O = sequence.indexOf('S');
}
if (sequence.indexOf('T') != -1
&& sequence.indexOf('T') < indexBionLossH2O) {
indexBionLossH2O = sequence.indexOf('T');
}
if (sequence.indexOf('D') != -1
&& sequence.indexOf('D') < indexBionLossH2O) {
indexBionLossH2O = sequence.indexOf('D');
}
if (sequence.indexOf('E') != -1
&& sequence.indexOf('E') < indexBionLossH2O) {
indexBionLossH2O = sequence.indexOf('E');
}
return indexBionLossH2O;
}
/**
* This method calculates the start position of a possible H2O loss for the
* Y-ion series. The returning variable is used for the H2O-loss
* fragmentions calculation. This variable holds the smallest index of
* S|T|E|D amino acid residue. These aminoacids can loose their H2O.
*
* @param String
* sequence
* @return int index.
*/
public static int getFirstYionLossH2O(String sequence) {
int indexYionLossH2O = 0;
if (sequence.indexOf('S') != -1
&& sequence.indexOf('S') > indexYionLossH2O) {
indexYionLossH2O = sequence.indexOf('S');
}
if (sequence.indexOf('T') != -1
&& sequence.indexOf('T') > indexYionLossH2O) {
indexYionLossH2O = sequence.indexOf('T');
}
if (sequence.indexOf('D') != -1
&& sequence.indexOf('D') > indexYionLossH2O) {
indexYionLossH2O = sequence.indexOf('D');
}
if (sequence.indexOf('E') != -1
&& sequence.indexOf('E') > indexYionLossH2O) {
indexYionLossH2O = sequence.indexOf('E');
}
return indexYionLossH2O;
}
/**
* This method calculates the start position of a possible NH3 loss for the
* B-ion series. The returning variable is used for the NH3-loss
* fragmentions calculation. This variable holds the smallest index of
* R|K|N|Q amino acid residue. These amino acids can loose their NH3.
*
* @param String
* sequence
* @return int index.
*/
public static int getFirstBionLossNH3(String sequence) {
int indexBionLossNH3 = sequence.length() - 1;
if (sequence.indexOf('R') != -1
&& sequence.indexOf('R') < indexBionLossNH3) {
indexBionLossNH3 = sequence.indexOf('R');
}
if (sequence.indexOf('K') != -1
&& sequence.indexOf('K') < indexBionLossNH3) {
indexBionLossNH3 = sequence.indexOf('K');
}
if (sequence.indexOf('N') != -1
&& sequence.indexOf('N') < indexBionLossNH3) {
indexBionLossNH3 = sequence.indexOf('N');
}
if (sequence.indexOf('Q') != -1
&& sequence.indexOf('Q') < indexBionLossNH3) {
indexBionLossNH3 = sequence.indexOf('Q');
}
return indexBionLossNH3;
}
/**
* This method calculates the start position of a possible NH3 loss for the
* Y-ion series. The returning variable is used for the NH3-loss
* fragmentions calculation. This variable holds the smallest index of
* R|K|N|Q amino acid residue. These aminoacids can loose their NH3.
*
* @param String
* sequence
* @return int index.
*/
public static int getFirstYionLossNH3(String sequence) {
int indexYionLossNH3 = 0;
if (sequence.indexOf('R') != -1
&& sequence.indexOf('R') > indexYionLossNH3) {
indexYionLossNH3 = sequence.indexOf('R');
}
if (sequence.indexOf('K') != -1
&& sequence.indexOf('K') > indexYionLossNH3) {
indexYionLossNH3 = sequence.indexOf('K');
}
if (sequence.indexOf('N') != -1
&& sequence.indexOf('N') > indexYionLossNH3) {
indexYionLossNH3 = sequence.indexOf('N');
}
if (sequence.indexOf('Q') != -1
&& sequence.indexOf('Q') > indexYionLossNH3) {
indexYionLossNH3 = sequence.indexOf('Q');
}
return indexYionLossNH3;
}
/**
* This method calculates fragment ions b and y.
*/
public static double[] calculatePeptideMasses(
HashMap<String, Double> defaultMasses, String sequence,
HashMap<Integer, ModificationPeptide> modifications) {
int length = sequence.length();
String aminoKey;
// Calculated the mass of each amino acid including detected
// modification
double[] peptideMasses = new double[length];
for (int i = 0; i < length; i++) {
// This double will hold the mass of the peptideUnit.
double aminoMass = 0.0;
/*
* Check if there is a N-Terminal modification, if there is one,
* count the mass of the N-terminal modification to the mass of the
* first amino acid.
*/
if (i == 0) {
if (modifications.containsKey(i))
aminoMass += modifications.get(i).getMass();
}
/*
* Check if there is a C-Terminal modification, if there is one,
* count the mass of the C-terminal modification to the mass of the
* last amino acid.
*/
if (i == length - 1) {
if (modifications.containsKey(i + 2))
aminoMass += modifications.get(i + 2).getMass();
}
// For aa i, count its mass to the UnitMass.
aminoKey = Character.toString(sequence.charAt(i));
aminoMass = aminoMass + defaultMasses.get(aminoKey);
/*
* If there is a modification on aa i, count the mass at the
* UnitMass. if the modification is fixed , don't add the mass
* because Mascot already included an equivalent modified amino acid
* mass.
*/
if (modifications.containsKey(i + 1)) {
ModificationPeptide mod = modifications.get(i + 1);
if (mod.isFixed())
aminoMass += mod.getMass();
}
peptideMasses[i] = aminoMass;
}
return peptideMasses;
}
/**
* This method calculates fragment ions b.
*/
public static Vector<FragmentIon> calculateBions(double[] peptideMasses,
double hydrogenMass) {
Vector<FragmentIon> bIons = new Vector<FragmentIon>();
for (int i = 1; i < peptideMasses.length; i++) {
double bMass = 0.0;
/*
* Sum all the peptides from left until the current position.
* Finally add 1 extra hydrogen on the N-terminal AA if there is no
* fixed N-terminal modification. A B-ion has no new components at
* its C-terminal end.
*/
for (int j = 0; j < i; j++) {
bMass += peptideMasses[j];
}
bMass = bMass + hydrogenMass;
bIons.add(new FragmentIon(bMass, FragmentIonType.B_ION, i));
}
return bIons;
}
/**
* This method calculates fragment ions y.
*/
public static Vector<FragmentIon> calculateYions(double[] peptideMasses,
double hydrogenMass, double oxygenMass) {
Vector<FragmentIon> yIons = new Vector<FragmentIon>();
double ctermMass = hydrogenMass + oxygenMass;
for (int i = 1; i < peptideMasses.length; i++) {
double yMass = 0.0;
/*
* Sum all the peptides from right until the current position.
* Finally add 1 extra hydroxyl on the C-terminal AA. A Y-ion also
* has 2 extra Hydrogens on its N-terminal end (NH in peptide bond,
* NH3+ when its free).
*/
for (int j = 0; j < i; j++) {
yMass += peptideMasses[(peptideMasses.length - 1) - j];
}
yMass = yMass + ctermMass + (2 * hydrogenMass);
yIons.add(new FragmentIon(yMass, FragmentIonType.Y_ION, i));
}
return yIons;
}
/**
* Return b-ions plus 'CO' minus 'H2' (a-ions).
*
* @return Vector<FragmentIon> aIons.
*/
public static Vector<FragmentIon> calculateAions(FragmentIon[] bIons,
double carbonMass, double oxygenMass, double hydrogenMass) {
Vector<FragmentIon> aIons = new Vector<FragmentIon>();
double mass;
double CO = carbonMass + oxygenMass;
double H2 = hydrogenMass * 2;
for (int i = 0; i < bIons.length; i++) {
// b-ion minus 'CO' plus 'H2'
mass = bIons[i].getMass() - CO + H2;
aIons.add(new FragmentIon(mass, FragmentIonType.A_ION, (i + 1)));
}
return aIons;
}
/**
* Return b-ions plus 'NH3' (c-ions).
*
* @return Vector<FragmentIon> cIons.
*/
public static Vector<FragmentIon> calculateCions(FragmentIon[] bIons,
double nitrogenMass, double hydrogenMass) {
Vector<FragmentIon> cIons = new Vector<FragmentIon>();
double mass;
double NH3 = nitrogenMass + (hydrogenMass * 3);
for (int i = 0; i < bIons.length; i++) {
// b-ion plus 'NH3'
mass = bIons[i].getMass() + NH3;
cIons.add(new FragmentIon(mass, FragmentIonType.C_ION, (i + 1)));
}
return cIons;
}
/**
* Return y-ion plus 'CO', minus 'H2' (x-ions).
*
* @return Vector<FragmentIon> zIons.
*/
public static Vector<FragmentIon> calculateXions(FragmentIon[] yIons,
double carbonMass, double oxygenMass, double hydrogenMass) {
Vector<FragmentIon> xIons = new Vector<FragmentIon>();
double mass;
double CO = carbonMass + oxygenMass;
double H2 = hydrogenMass * 2;
for (int i = 0; i < yIons.length; i++) {
// y-ion minus 'NH3' plus 'H2'
mass = yIons[i].getMass() + CO - H2;
xIons.add(new FragmentIon(mass, FragmentIonType.X_ION, (i + 1)));
}
return xIons;
}
/**
* Return y-ions minus 'NH3' (z-ions).
*
* @return Vector<FragmentIon> zIons.
*/
public static Vector<FragmentIon> calculateZions(FragmentIon[] bIons,
double nitrogenMass, double hydrogenMass) {
Vector<FragmentIon> cIons = new Vector<FragmentIon>();
double mass;
double NH3 = nitrogenMass + (hydrogenMass * 3);
for (int i = 0; i < bIons.length; i++) {
// y-ion minus 'NH3'
mass = bIons[i].getMass() - NH3;
cIons.add(new FragmentIon(mass, FragmentIonType.Z_ION, (i + 1)));
}
return cIons;
}
/**
* Return z-ions plus 'H' (zh-ions).
*
* @return Vector<FragmentIon> zhIons.
*/
public static Vector<FragmentIon> calculateZHions(FragmentIon[] zIons,
double hydrogenMass) {
Vector<FragmentIon> zhIons = new Vector<FragmentIon>();
double mass;
for (int i = 0; i < zIons.length; i++) {
// b-ion minus 'CO' plus 'H2'
mass = zIons[i].getMass() + hydrogenMass;
zhIons.add(new FragmentIon(mass, FragmentIonType.ZH_ION, (i + 1)));
}
return zhIons;
}
/**
* Return z-ions plus 'H2' (zhh-ions).
*
* @return Vector<FragmentIon> zhhIons.
*/
public static Vector<FragmentIon> calculateZHHions(FragmentIon[] zIons,
double hydrogenMass) {
Vector<FragmentIon> zhhIons = new Vector<FragmentIon>();
double mass;
for (int i = 0; i < zIons.length; i++) {
// z-ion plus 'H2'
mass = zIons[i].getMass() + (hydrogenMass * 2);
zhhIons.add(new FragmentIon(mass, FragmentIonType.ZHH_ION, (i + 1)));
}
return zhhIons;
}
/**
* Returns all double charged ions.
*
* @return Vector<FragmentIon> doubleChargedIons
*/
public static Vector<FragmentIon> calculateDoubleChargedIons(
FragmentIon[] bIons, double hydrogenMass, FragmentIonType ionType) {
Vector<FragmentIon> bDoubleIons = new Vector<FragmentIon>();
double mass;
for (int i = 0; i < bIons.length; i++) {
// b-ion plus 'H' over a double charge
mass = (bIons[i].getMass() + hydrogenMass) / 2.0;
bDoubleIons.add(new FragmentIon(mass, ionType, i + 1));
}
return bDoubleIons;
}
/**
* Returns Ions minus 'H2O', single and double charge.
*
* @return Vector<FragmentIon> ions - H2O
*/
public static Vector<FragmentIon> calculateIonsLossH2O(FragmentIon[] bIons,
double hydrogenMass, double oxygenMass, int indexFirstIonLossH2O,
boolean doubleCharged, FragmentIonType ionType) {
Vector<FragmentIon> bIonsLossH20 = new Vector<FragmentIon>();
double lossMass;
if (doubleCharged)
lossMass = hydrogenMass + oxygenMass;
else
lossMass = (hydrogenMass * 2) + oxygenMass;
double mass;
// Verify position of fist aa who can loose H2O
if (indexFirstIonLossH2O != bIons.length) {
for (int i = indexFirstIonLossH2O; i < bIons.length; i++) {
// b-ion minus 'H2O'
mass = bIons[i].getMass() - lossMass;
if (doubleCharged)
mass /= 2.0;
bIonsLossH20.add(new FragmentIon(mass, ionType, i + 1));
}
}
return bIonsLossH20;
}
/**
* Returns Ions minus 'NH3', single and double charge.
*
* @return Vector<FragmentIon> ions - NH3
*/
public static Vector<FragmentIon> calculateIonsLossNH3(FragmentIon[] bIons,
double hydrogenMass, double nitrogenMass, int indexFirstIonLossNH3,
boolean doubleCharged, FragmentIonType ionType) {
Vector<FragmentIon> bIonsLossH20 = new Vector<FragmentIon>();
double lossMass;
if (doubleCharged)
lossMass = nitrogenMass + (hydrogenMass * 2);
else
lossMass = nitrogenMass + (hydrogenMass * 3);
double mass;
// The peptide must be checked for position of the first amino acid who
// losses NH3
if (indexFirstIonLossNH3 != bIons.length) {
for (int i = indexFirstIonLossNH3; i < bIons.length; i++) {
// b-ion minus 'NH3'
mass = bIons[i].getMass() - lossMass;
if (doubleCharged)
mass /= 2.0;
bIonsLossH20.add(new FragmentIon(mass, ionType, i + 1));
}
}
return bIonsLossH20;
}
/**
* Returns precursor ions , minus 'NH3' and minus H2O.
*
* @return Vector<FragmentIon> precursorIons
*/
public static FragmentIon[] calculatePrecursorIons(double precursorMass,
int charge, double hydrogenMass, double oxygenMass,
double nitrogenMass) {
Vector<FragmentIon> precursorIons = new Vector<FragmentIon>();
double H2O = (hydrogenMass) * 2 + oxygenMass;
double NH3 = nitrogenMass + (hydrogenMass * 3);
if (precursorMass != 0.0) {
precursorIons.add(new FragmentIon(precursorMass,
FragmentIonType.PRECURSOR, 0));
double mass = precursorMass - (H2O / charge);
precursorIons.add(new FragmentIon(mass,
FragmentIonType.PRECURSOR_H2O, 0));
mass = precursorMass - (NH3 / charge);
precursorIons.add(new FragmentIon(mass,
FragmentIonType.PRECURSOR_NH3, 0));
}
return precursorIons.toArray(new FragmentIon[0]);
}
/**
* Returns immonium ions
*
* @return Vector<FragmentIon> immoniumIons
*/
public static FragmentIon[] calculateImmoniumIons(String sequence,
HashMap<String, Double> defaultMasses) {
Vector<FragmentIon> immoniumIons = new Vector<FragmentIon>();
for (int i = 0; i < sequence.length(); i++) {
char c = sequence.charAt(i);
switch (c) {
case 'A' :
immoniumIons.add(new FragmentIon(defaultMasses.get("A"),
FragmentIonType.IMMONIUM_A, 0));
break;
case 'R' :
immoniumIons.add(new FragmentIon(defaultMasses.get("R"),
FragmentIonType.IMMONIUM_R, 0));
break;
case 'N' :
immoniumIons.add(new FragmentIon(defaultMasses.get("N"),
FragmentIonType.IMMONIUM_N, 0));
break;
case 'D' :
immoniumIons.add(new FragmentIon(defaultMasses.get("D"),
FragmentIonType.IMMONIUM_D, 0));
break;
case 'C' :
immoniumIons.add(new FragmentIon(defaultMasses.get("C"),
FragmentIonType.IMMONIUM_C, 0));
break;
case 'E' :
immoniumIons.add(new FragmentIon(defaultMasses.get("E"),
FragmentIonType.IMMONIUM_E, 0));
break;
case 'Q' :
immoniumIons.add(new FragmentIon(defaultMasses.get("Q"),
FragmentIonType.IMMONIUM_Q, 0));
break;
case 'G' :
immoniumIons.add(new FragmentIon(defaultMasses.get("G"),
FragmentIonType.IMMONIUM_G, 0));
break;
case 'H' :
immoniumIons.add(new FragmentIon(defaultMasses.get("H"),
FragmentIonType.IMMONIUM_H, 0));
break;
case 'I' :
immoniumIons.add(new FragmentIon(defaultMasses.get("I"),
FragmentIonType.IMMONIUM_I, 0));
break;
case 'L' :
immoniumIons.add(new FragmentIon(defaultMasses.get("L"),
FragmentIonType.IMMONIUM_L, 0));
break;
case 'K' :
immoniumIons.add(new FragmentIon(defaultMasses.get("K"),
FragmentIonType.IMMONIUM_K, 0));
break;
case 'M' :
immoniumIons.add(new FragmentIon(defaultMasses.get("M"),
FragmentIonType.IMMONIUM_M, 0));
break;
case 'F' :
immoniumIons.add(new FragmentIon(defaultMasses.get("F"),
FragmentIonType.IMMONIUM_F, 0));
break;
case 'P' :
immoniumIons.add(new FragmentIon(defaultMasses.get("P"),
FragmentIonType.IMMONIUM_P, 0));
break;
case 'S' :
immoniumIons.add(new FragmentIon(defaultMasses.get("S"),
FragmentIonType.IMMONIUM_S, 0));
break;
case 'T' :
immoniumIons.add(new FragmentIon(defaultMasses.get("T"),
FragmentIonType.IMMONIUM_T, 0));
break;
case 'W' :
immoniumIons.add(new FragmentIon(defaultMasses.get("W"),
FragmentIonType.IMMONIUM_W, 0));
break;
case 'Y' :
immoniumIons.add(new FragmentIon(defaultMasses.get("Y"),
FragmentIonType.IMMONIUM_Y, 0));
break;
case 'V' :
immoniumIons.add(new FragmentIon(defaultMasses.get("V"),
FragmentIonType.IMMONIUM_V, 0));
break;
}
}
return immoniumIons.toArray(new FragmentIon[0]);
}
/**
* Return the matched ions (MS/MS masses) between a calculated fragment ions
* and scan's data points
*
* @param scanDataPoints
* @param fragmentIons
* @param fragmentIonMassErrorTol
* @param intensityThreshold
* @return
*/
public static DataPoint[] getMatchedIons(DataPoint[] scanDataPoints,
FragmentIon[] fragmentIons, double fragmentIonMassErrorTol,
double intensityThreshold) {
DataPoint[] matchedDataPoints = null;
return matchedDataPoints;
}
/**
* Returns the coverage of the ion series.
*
* @param dataPoints
* @param peptide
* @param ionType
* @param intensityThreshold
* @return
*/
public static double getIonCoverage(DataPoint[] dataPoints,
Peptide peptide, SerieIonType ionType, double intensityThreshold) {
PeptideFragmentation fragmentation = peptide.getFragmentation();
FragmentIon[] fragmentIons = fragmentation.getFragmentIons(ionType);
PeptideIdentityDataFile peptideDataFile = peptide.getScan()
.getPeptideDataFile();
double fragmentIonMassErrorTol = peptideDataFile
.getFragmentIonMassErrorTolerance();
DataPoint[] matchedDataPoints = getMatchedIons(dataPoints,
fragmentIons, fragmentIonMassErrorTol, intensityThreshold);
double ionCoverage = calculateSerieCoverage(matchedDataPoints,
fragmentIons);
return ionCoverage;
}
/**
* Calculates the ion coverage
*
* @param matchedDataPoints
* @param fragmentIons
* @return
*/
public static double calculateSerieCoverage(DataPoint[] matchedDataPoints,
FragmentIon[] fragmentIons) {
// TODO
return 0;
}
}