package com.compomics.util.preferences;
import com.compomics.util.Util;
import com.compomics.util.experiment.biology.AminoAcid;
import com.compomics.util.experiment.biology.Enzyme;
import com.compomics.util.experiment.biology.EnzymeFactory;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
/**
* This class groups the preferences for the digestion of proteins.
*
* @author Marc Vaudel
*/
public class DigestionPreferences implements Serializable {
/**
* Enum for the different types of enzyme specificity.
*/
public enum Specificity {
/**
* Specific at both termini.
*/
specific(0, "Specific"),
/**
* Specific at only one of the termini.
*/
semiSpecific(1, "Semi-Specific"),
/**
* Specific at the N-terminus only.
*/
specificNTermOnly(2, "N-term Specific"),
/**
* Specific at the C-terminus only.
*/
specificCTermOnly(3, "C-term Specific");
/**
* The index.
*/
public final int index;
/**
* The name.
*/
public final String name;
/**
* Constructor.
*
* @param index the index as integer
* @param name the name
*/
private Specificity(int index, String name) {
this.index = index;
this.name = name;
}
/**
* Returns the specificity of the given index.
*
* @param index the index of the specificity
*
* @return the corresponding specificity
*/
public static Specificity getSpecificity(int index) {
for (Specificity specificity : values()) {
if (specificity.index == index) {
return specificity;
}
}
throw new IllegalArgumentException("No specificity found for index " + index + ".");
}
/**
* Returns the different options as command line description.
*
* @return the different options as command line description
*/
public static String getCommandLineDescription() {
StringBuilder stringBuilder = new StringBuilder();
for (Specificity specificity : values()) {
if (stringBuilder.length() > 0) {
stringBuilder.append(", ");
}
stringBuilder.append(specificity.index).append(": ").append(specificity.name);
}
return stringBuilder.toString();
}
@Override
public String toString() {
return name;
}
}
/**
* Enum for the different types of digestion.
*/
public enum CleavagePreference {
/**
* Digestion with an enzyme.
*/
enzyme(0, "Enzyme"),
/**
* Unspecific digestion.
*/
unSpecific(1, "Unspecific"),
/**
* Whole protein, no digestion.
*/
wholeProtein(2, "Whole Protein");
/**
* The index.
*/
public final int index;
/**
* The name.
*/
public final String name;
/**
* Constructor.
*
* @param index the index as integer
* @param name the name
*/
private CleavagePreference(int index, String name) {
this.index = index;
this.name = name;
}
/**
* Returns the cleavage preference of the given index.
*
* @param index the index of the cleavage preference
*
* @return the corresponding cleavage preference
*/
public static CleavagePreference getCleavagePreferences(int index) {
for (CleavagePreference cleavagePreference : values()) {
if (cleavagePreference.index == index) {
return cleavagePreference;
}
}
throw new IllegalArgumentException("No cleavage preference found for index " + index + ".");
}
/**
* Returns the different options as command line description.
*
* @return the different options as command line description
*/
public static String getCommandLineDescription() {
StringBuilder stringBuilder = new StringBuilder();
for (CleavagePreference cleavagePreference : values()) {
if (stringBuilder.length() > 0) {
stringBuilder.append(", ");
}
stringBuilder.append(cleavagePreference.index).append(": ").append(cleavagePreference.name);
}
return stringBuilder.toString();
}
@Override
public String toString() {
return name;
}
}
/**
* Boolean indicating whether the sample was not digested.
*/
private CleavagePreference cleavagePreference;
/**
* List of enzyme used.
*/
private ArrayList<Enzyme> enzymes;
/**
* Number of allowed missed cleavages.
*/
private HashMap<String, Integer> nMissedCleavages;
/**
* The specificity of the enzyme.
*/
private HashMap<String, Specificity> specificity;
/**
* Constructor for empty preferences.
*/
public DigestionPreferences() {
}
/**
* Clones the given preferences.
*
* @param digestionPreferences the preferences to clone
*
* @return a new object containing the same preferences
*/
public static DigestionPreferences clone(DigestionPreferences digestionPreferences) {
DigestionPreferences clone = new DigestionPreferences();
clone.setCleavagePreference(digestionPreferences.getCleavagePreference());
if (digestionPreferences.getCleavagePreference() == DigestionPreferences.CleavagePreference.enzyme) {
for (Enzyme enzyme : digestionPreferences.getEnzymes()) {
clone.addEnzyme(enzyme);
String enzymeName = enzyme.getName();
clone.setSpecificity(enzymeName, digestionPreferences.getSpecificity(enzymeName));
clone.setnMissedCleavages(enzymeName, digestionPreferences.getnMissedCleavages(enzymeName));
}
}
return clone;
}
/**
* Returns default digestion preferences. Trypsin specific with two missed
* cleavages.
*
* @return default digestion preferences
*/
public static DigestionPreferences getDefaultPreferences() {
DigestionPreferences digestionPreferences = new DigestionPreferences();
digestionPreferences.setCleavagePreference(CleavagePreference.enzyme);
String enzymeName = "Trypsin";
Enzyme trypsin = EnzymeFactory.getInstance().getEnzyme(enzymeName);
digestionPreferences.addEnzyme(trypsin);
digestionPreferences.setnMissedCleavages(enzymeName, 2);
return digestionPreferences;
}
/**
* Returns a boolean indicating whether enzyme settings were set.
*
* @return a boolean indicating whether enzyme settings were set
*/
public boolean hasEnzymes() {
return enzymes != null && !enzymes.isEmpty();
}
/**
* Returns the enzymes used for digestion in a list.
*
* @return the enzymes used for digestion in a list
*/
public ArrayList<Enzyme> getEnzymes() {
return enzymes;
}
/**
* Sets the enzymes used for digestion.
*
* @param enzymes the enzymes used for digestion in a list
*/
public void setEnzymes(ArrayList<Enzyme> enzymes) {
this.enzymes = enzymes;
}
/**
* Adds an enzyme. The specificity of the enzyme is set by default to
* specific and the number of allowed missed cleavages to 0.
*
* @param enzyme an enzyme used for digestion.
*/
public void addEnzyme(Enzyme enzyme) {
if (enzymes == null) {
enzymes = new ArrayList<Enzyme>(1);
}
enzymes.add(enzyme);
setSpecificity(enzyme.getName(), Specificity.specific);
setnMissedCleavages(enzyme.getName(), 0);
}
/**
* Clears the parameters.
*/
public void clear() {
cleavagePreference = null;
enzymes = null;
nMissedCleavages = null;
specificity = null;
}
/**
* Clears the enzymes set including specificity and missed cleavages.
*/
public void clearEnzymes() {
enzymes = null;
nMissedCleavages = null;
specificity = null;
}
/**
* Returns the number of allowed missed cleavages for the given enzyme. Null
* if not set.
*
* @param enzymeName the name of the enzyme
*
* @return the number of allowed missed cleavages
*/
public Integer getnMissedCleavages(String enzymeName) {
if (nMissedCleavages == null) {
return null;
}
return nMissedCleavages.get(enzymeName);
}
/**
* Sets the number of allowed missed cleavages.
*
* @param enzymeName the name of the enzyme
* @param enzymeMissedCleavages the number of allowed missed cleavages
*/
public void setnMissedCleavages(String enzymeName, int enzymeMissedCleavages) {
if (nMissedCleavages == null) {
nMissedCleavages = new HashMap<String, Integer>(1);
}
nMissedCleavages.put(enzymeName, enzymeMissedCleavages);
}
/**
* Returns the expected specificity of the given enzyme. Null if not set.
*
* @param enzymeName the name of the enzyme
*
* @return the specificity
*/
public Specificity getSpecificity(String enzymeName) {
if (specificity == null) {
return null;
}
Specificity enzymeSpecificity = specificity.get(enzymeName);
return enzymeSpecificity;
}
/**
* Sets the expected specificity of the enzyme.
*
* @param enzymeName the name of the enzyme
* @param enzymeSpecificity the expected specificity of the enzyme
*/
public void setSpecificity(String enzymeName, Specificity enzymeSpecificity) {
if (specificity == null) {
specificity = new HashMap<String, Specificity>(1);
}
specificity.put(enzymeName, enzymeSpecificity);
}
/**
* Returns the cleavage preferences.
*
* @return the cleavage preferences
*/
public CleavagePreference getCleavagePreference() {
return cleavagePreference;
}
/**
* Sets the cleavage preferences.
*
* @param cleavagePreference the cleavage preferences
*/
public void setCleavagePreference(CleavagePreference cleavagePreference) {
this.cleavagePreference = cleavagePreference;
}
/**
* Returns a short description of the parameters.
*
* @return a short description of the parameters
*/
public String getShortDescription() {
DigestionPreferences defaultPreferences = DigestionPreferences.getDefaultPreferences();
StringBuilder stringBuilder = new StringBuilder();
String newLine = System.getProperty("line.separator");
if (!defaultPreferences.isSameAs(this)) {
stringBuilder.append("Digestion: ");
switch (cleavagePreference) {
case wholeProtein:
stringBuilder.append("Whole Protein").append(newLine);
break;
case unSpecific:
stringBuilder.append("Unspecific").append(newLine);
break;
case enzyme:
for (Enzyme enzyme1 : enzymes) {
if (stringBuilder.length() > 0) {
stringBuilder.append(newLine);
}
Enzyme enzyme = enzyme1;
String enzymeName = enzyme.getName();
stringBuilder.append(enzymeName).append(", ").append(getSpecificity(enzymeName));
Integer nmc = getnMissedCleavages(enzymeName);
if (nmc != null) {
stringBuilder.append(", ").append(nmc).append(" missed cleavages");
}
}
break;
default:
throw new UnsupportedOperationException("Description not implemented for cleavage preference " + cleavagePreference + ".");
}
stringBuilder.append(".").append(newLine);
}
return stringBuilder.toString();
}
/**
* Returns a boolean indicating whether these digestion preferences are the
* same as the given other preferences.
*
* @param otherDigestionPreferences the other digestion preferences
*
* @return a boolean indicating whether these digestion preferences are the
* same as the given other preferences
*/
public boolean isSameAs(DigestionPreferences otherDigestionPreferences) {
if (cleavagePreference != otherDigestionPreferences.getCleavagePreference()) {
return false;
}
ArrayList<Enzyme> otherEnzymes = otherDigestionPreferences.getEnzymes();
if ((enzymes != null && otherEnzymes == null)
|| (enzymes == null && otherEnzymes != null)) {
return false;
}
if (enzymes != null && otherEnzymes != null) {
if (enzymes.size() != otherEnzymes.size()) {
return false;
}
ArrayList<String> enzymeNames = new ArrayList<String>(enzymes.size());
for (Enzyme enzyme : enzymes) {
enzymeNames.add(enzyme.getName());
}
ArrayList<String> otherNames = new ArrayList<String>(otherEnzymes.size());
for (Enzyme enzyme : otherEnzymes) {
otherNames.add(enzyme.getName());
}
if (!Util.sameLists(enzymeNames, otherNames)) {
return false;
}
for (String enzymeName : enzymeNames) {
if (getSpecificity(enzymeName) != otherDigestionPreferences.getSpecificity(enzymeName)
|| !getnMissedCleavages(enzymeName).equals(otherDigestionPreferences.getnMissedCleavages(enzymeName))) {
return false;
}
}
}
return true;
}
/**
* Get the X!Tandem enzyme format.
*
* @return the enzyme X!Tandem format as String
*/
public String getXTandemFormat() {
switch (cleavagePreference) {
case wholeProtein:
return "";
case unSpecific:
return "[X]|[X]";
case enzyme:
StringBuilder result = new StringBuilder();
for (Enzyme enzyme : enzymes) {
if (result.length() > 0) {
result.append(",");
}
Specificity specificity = getSpecificity(enzyme.getName());
if (enzyme.getAminoAcidBefore().size() > 0) {
result.append("[");
for (Character aa : enzyme.getAminoAcidBefore()) {
result.append(aa);
}
result.append("]");
}
if (enzyme.getRestrictionBefore().size() > 0) {
result.append("{");
for (Character aa : enzyme.getRestrictionBefore()) {
result.append(aa);
}
result.append("}");
}
if (enzyme.getAminoAcidBefore().isEmpty() && enzyme.getRestrictionBefore().isEmpty()) {
result.append("[X]");
}
result.append("|");
if (enzyme.getAminoAcidAfter().size() > 0) {
result.append("[");
for (Character aa : enzyme.getAminoAcidAfter()) {
result.append(aa);
}
result.append("]");
}
if (enzyme.getRestrictionAfter().size() > 0) {
result.append("{");
for (Character aa : enzyme.getRestrictionAfter()) {
result.append(aa);
}
result.append("}");
}
if (enzyme.getAminoAcidAfter().isEmpty() && enzyme.getRestrictionAfter().isEmpty()) {
result.append("[X]");
}
}
return result.toString();
default:
throw new UnsupportedOperationException("X!Tandem format not implemented for cleavage preference " + cleavagePreference + ".");
}
}
/**
* Get the MyriMatch enzyme format. In case multiple enzymes are present all
* possible cleavage sites will be included.
*
* @return the enzyme MyriMatch format as String
*/
public String getMyriMatchFormat() {
// example: trypsin corresponds to "[|R|K . . ]"
// details: http://www.mc.vanderbilt.edu/root/vumc.php?site=msrc/bioinformatics&doc=27121
String result = "[";
for (Enzyme enzyme : enzymes) {
if (enzyme.getAminoAcidBefore().size() > 0) {
for (Character aa : enzyme.getAminoAcidBefore()) {
result += "|" + aa;
}
result += " ";
} else {
result += " ";
}
}
HashSet<Character> commonRestrictionAfter;
if (enzymes.size() == 1) {
commonRestrictionAfter = enzymes.get(0).getRestrictionAfter();
} else {
commonRestrictionAfter = new HashSet<Character>();
for (Character aa : enzymes.get(0).getRestrictionAfter()) {
boolean missing = false;
for (Enzyme enzyme : enzymes) {
if (!enzyme.getRestrictionAfter().contains(aa)) {
missing = true;
break;
}
}
if (!missing) {
commonRestrictionAfter.add(aa);
}
}
}
if (commonRestrictionAfter.size() > 0) {
String temp = "";
for (Character aa : AminoAcid.getUniqueAminoAcids()) {
if (!commonRestrictionAfter.contains(aa)) {
if (!temp.isEmpty()) {
temp += "|";
}
temp += aa;
}
}
result += temp + " ";
} else {
result += ". ";
}
HashSet<Character> commonRestrictionBefore;
if (enzymes.size() == 1) {
commonRestrictionBefore = enzymes.get(0).getRestrictionBefore();
} else {
commonRestrictionBefore = new HashSet<Character>();
for (Character aa : enzymes.get(0).getRestrictionBefore()) {
boolean missing = false;
for (Enzyme enzyme : enzymes) {
if (!enzyme.getRestrictionBefore().contains(aa)) {
missing = true;
break;
}
}
if (!missing) {
commonRestrictionBefore.add(aa);
}
}
}
if (commonRestrictionBefore.size() > 0) {
String temp = "";
for (Character aa : AminoAcid.getUniqueAminoAcids()) {
if (!commonRestrictionBefore.contains(aa)) {
if (!temp.isEmpty()) {
temp += "|";
}
temp += aa;
}
}
result += temp + " ";
} else {
result += ". ";
}
for (Enzyme enzyme : enzymes) {
if (enzyme.getAminoAcidAfter().size() > 0) {
String temp = "";
for (Character aa : enzyme.getAminoAcidAfter()) {
if (!temp.isEmpty()) {
temp += "|";
}
temp += aa;
}
result += temp + "|";
}
}
return result + "]";
}
}