package com.compomics.util.experiment.identification.amino_acid_tags; import com.compomics.util.experiment.biology.AminoAcid; import com.compomics.util.experiment.biology.AminoAcidPattern; import com.compomics.util.experiment.biology.AminoAcidSequence; import com.compomics.util.experiment.biology.PTM; import com.compomics.util.experiment.biology.PTMFactory; import com.compomics.util.experiment.identification.matches.ModificationMatch; import java.util.ArrayList; import java.util.HashMap; /** * Segment of sequence indexed on a protein sequence. * * @author Marc Vaudel */ public class SequenceSegment { /** * The index of the terminus on the protein. */ private int terminalIndex; /** * The length of the segment. */ private int length = 0; /** * Map of mutations: index on the segment - mutated character. */ private HashMap<Integer, Character> mutations = null; /** * Map of the PTMs: index on the segment - name of the modification. */ private HashMap<Integer, String> modificationMatches = null; /** * The previous segment in case this one is a follow-up. */ private SequenceSegment previousSegment = null; /** * Boolean indicating whether the segment is sequencing from the N (true) or * the C (false) terminus. */ public final boolean nTerminus; /** * The index of the mutation. */ private Integer mutationIndex = null; /** * The mutated amino acid. */ private Character mutation = null; /** * The modification located at the terminus. */ private String modificationAtTerminus = null; /** * The mass of the segment. */ private double mass = 0; /** * Constructor. * * @param terminalIndex the index of the segment on the protein * @param nTerminus indicates whether the segment is indexed to the N (true) * or C (false) terminus */ public SequenceSegment(int terminalIndex, boolean nTerminus) { this.nTerminus = nTerminus; this.terminalIndex = terminalIndex; } /** * Constructor. * * @param sequenceSegment another sequence segment */ public SequenceSegment(SequenceSegment sequenceSegment) { this.nTerminus = sequenceSegment.nTerminus; this.terminalIndex = sequenceSegment.getTerminalIndex(); length = sequenceSegment.length(); previousSegment = sequenceSegment; Integer otherMutationIndex = sequenceSegment.getMutationIndex(); if (otherMutationIndex != null) { mutationIndex = otherMutationIndex; mutation = sequenceSegment.getMutation(); } mass = sequenceSegment.getMass(); } /** * Returns the length of the segment. * * @return the length of the segment */ public int length() { return length; } /** * Returns a map of mutations on that segment: index on the segment - * mutated character. * * @return a map of mutations on that segment */ public HashMap<Integer, Character> getMutations() { if (previousSegment != null) { HashMap<Integer, Character> previousMutations = previousSegment.getMutations(); if (previousMutations != null) { if (mutations == null) { if (mutation == null) { return previousMutations; } else { HashMap<Integer, Character> tempMutations = new HashMap<Integer, Character>(previousMutations.size()); tempMutations.put(mutationIndex, mutation); return tempMutations; } } mutations.putAll(previousMutations); } } if (mutation != null) { if (mutations == null) { HashMap<Integer, Character> tempMutations = new HashMap<Integer, Character>(1); tempMutations.put(mutationIndex, mutation); return tempMutations; } mutations.put(mutationIndex, mutation); } return mutations; } /** * Returns a map of modifications on that segment: index on the segment - * modification name. * * @return a map of modifications on that segment */ public HashMap<Integer, String> getModificationMatches() { if (previousSegment != null) { HashMap<Integer, String> previousModifications = previousSegment.getModificationMatches(); if (previousModifications != null) { if (modificationMatches == null) { if (modificationAtTerminus == null) { return previousModifications; } else { HashMap<Integer, String> tempModifications = new HashMap<Integer, String>(previousModifications.size()); tempModifications.put(length, modificationAtTerminus); return tempModifications; } } modificationMatches.putAll(previousModifications); } } if (modificationAtTerminus != null) { if (modificationMatches == null) { HashMap<Integer, String> tempModifications = new HashMap<Integer, String>(1); tempModifications.put(length, modificationAtTerminus); return tempModifications; } modificationMatches.put(length, modificationAtTerminus); } return modificationMatches; } /** * Returns the index of the terminal on the protein sequence. * * @return the index of the terminal on the protein sequence */ public int getTerminalIndex() { return terminalIndex; } /** * Returns the starting index of the segment on the protein. * * @return the starting index of the segment on the protein */ public int getIndexOnProtein() { if (nTerminus) { return terminalIndex + 1; } else { return terminalIndex - length; } } /** * Returns the mutation index, null if none. * * @return the mutation index */ public Integer getMutationIndex() { return mutationIndex; } /** * Returns the mutated amino acid, null if none. * * @return the amino acid at the terminus if mutated */ public Character getMutation() { return mutation; } /** * Returns the mass of the segment. * * @return the mass of the segment */ public double getMass() { return mass; } /** * Adds a mass to the segment. * * @param mass the mass to add */ public void addMass(double mass) { this.mass += mass; } /** * Appends a sequence segment to the terminus of sequencing. * * @param sequenceSegment a sequence segment */ public void appendTerminus(SequenceSegment sequenceSegment) { HashMap<Integer, Character> otherMutations = sequenceSegment.getMutations(); if (otherMutations != null) { if (mutations == null) { mutations = new HashMap<Integer, Character>(otherMutations.size()); } for (int index : otherMutations.keySet()) { mutations.put(index + length, otherMutations.get(index)); } } HashMap<Integer, String> otherModifications = sequenceSegment.getModificationMatches(); if (otherModifications != null) { if (modificationMatches == null) { modificationMatches = new HashMap<Integer, String>(otherModifications.size()); } for (int index : otherModifications.keySet()) { modificationMatches.put(index + length, otherModifications.get(index)); } } length += sequenceSegment.length(); if (nTerminus) { terminalIndex -= sequenceSegment.length(); } else { terminalIndex += sequenceSegment.length(); } Integer otherMutationIndex = sequenceSegment.getMutationIndex(); if (otherMutationIndex != null) { if (mutationIndex == null) { mutationIndex = otherMutationIndex; mutation = sequenceSegment.getMutation(); } else { if (mutations == null) { mutations = new HashMap<Integer, Character>(); mutations.put(otherMutationIndex, mutation); } } } mass += sequenceSegment.getMass(); } /** * Appends an amino acid sequence to the terminus of sequencing. * * @param aminoAcidSequence an amino acid sequence */ public void appendTerminus(AminoAcidSequence aminoAcidSequence) { HashMap<Integer, ArrayList<ModificationMatch>> otherModifications = aminoAcidSequence.getModificationMatches(); if (otherModifications != null) { if (modificationMatches == null) { modificationMatches = new HashMap<Integer, String>(otherModifications.size()); } for (int index : otherModifications.keySet()) { ArrayList<ModificationMatch> modificationMatchesList = otherModifications.get(index); if (modificationMatches.size() > 1) { throw new IllegalArgumentException("Two PTMs found on the same amino acid when mapping tags. Only one supported."); } modificationMatches.put(index + length, modificationMatchesList.get(0).getTheoreticPtm()); } } length += aminoAcidSequence.length(); if (nTerminus) { terminalIndex -= aminoAcidSequence.length(); } else { terminalIndex += aminoAcidSequence.length(); } mass += aminoAcidSequence.getMass(); } /** * Appends an amino acid pattern to the terminus of sequencing. * * @param aminoAcidPattern an amino acid pattern */ public void appendTerminus(AminoAcidPattern aminoAcidPattern) { HashMap<Integer, ArrayList<ModificationMatch>> otherModifications = aminoAcidPattern.getModificationMatches(); if (otherModifications != null) { if (modificationMatches == null) { modificationMatches = new HashMap<Integer, String>(otherModifications.size()); } for (int index : otherModifications.keySet()) { ArrayList<ModificationMatch> modificationMatchesList = otherModifications.get(index); if (modificationMatches.size() > 1) { throw new IllegalArgumentException("Two PTMs found on the same amino acid when mapping tags. Only one supported."); } modificationMatches.put(index + length, modificationMatchesList.get(0).getTheoreticPtm()); } } length += aminoAcidPattern.length(); if (nTerminus) { terminalIndex -= aminoAcidPattern.length(); } else { terminalIndex += aminoAcidPattern.length(); } mass += aminoAcidPattern.getMass(); } /** * Appends an amino acid to the terminus of sequencing. * * @param aminoAcid an amino acid */ public void appendTerminus(AminoAcid aminoAcid) { if (nTerminus) { terminalIndex--; } else { terminalIndex++; } length++; mass += aminoAcid.getMonoisotopicMass(); } /** * Adds a modification to the terminus of sequencing. * * @param modification the modification */ public void addModificationTerminus(String modification) { PTM ptm = PTMFactory.getInstance().getPTM(modification); addModificationTerminus(modification, ptm.getMass()); } /** * Adds a modification to the terminus of sequencing. * * @param modification the name of the modification * @param modificationMass the mass of the modification */ public void addModificationTerminus(String modification, double modificationMass) { modificationAtTerminus = modification; mass += modificationMass; } /** * Adds a mutation to the segment. * * @param index the index of the mutated amino acid * @param aa the mutated amino acid */ public void addMutation(Integer index, Character aa) { if (mutationIndex == null) { mutationIndex = index; mutation = aa; } else { if (mutations == null) { mutations = new HashMap<Integer, Character>(1); } mutations.put(index, aa); } } /** * Returns the number of mutations. * * @return the number of mutations */ public int getnMutations() { if (mutations == null) { if (mutationIndex == null) { return 0; } else { return 1; } } return mutations.size(); } /** * Returns the sequence of this segment. * * @param sequence the protein sequence * * @return the sequence of this segment */ public String getSegmentSequence(String sequence) { if (nTerminus) { return sequence.substring(terminalIndex + 1, terminalIndex + 1 + length); } else { return sequence.substring(terminalIndex - length, terminalIndex); } } }