+ "Error encountered in peptide " + peptideSequence + " spectrum " + spectrumTitle + " in spectrum file " + fileName + ".\n"
+ "Identification file: " + idFile.getName());
}
tempNames = ptmFactory.getExpectedPTMs(modificationProfile, peptide, seMass, ptmMassTolerance, sequenceMatchingPreferences);
} else if (fileReader instanceof DirecTagIdfileReader) {
PTM ptm = ptmFactory.getPTM(sePTM);
if (ptm == PTMFactory.unknownPTM) {
throw new IllegalArgumentException("PTM not recognized spectrum " + spectrumTitle + " of file " + fileName + ".");
}
tempNames = ptmFactory.getExpectedPTMs(modificationProfile, peptide, ptm.getMass(), ptmMassTolerance, sequenceMatchingPreferences);
} else {
throw new IllegalArgumentException("PTM mapping not implemented for the parsing of " + idFile.getName() + ".");
}
ArrayList<String> allNames = new ArrayList<String>();
for (ArrayList<String> namesAtAA : tempNames.values()) {
for (String name : namesAtAA) {
if (!allNames.contains(name)) {
allNames.add(name);
}
}
}
modNames.put(modMatch, allNames);
for (int pos : tempNames.keySet()) {
ArrayList<String> namesAtPosition = expectedNames.get(pos);
if (namesAtPosition == null) {
namesAtPosition = new ArrayList<String>(2);
expectedNames.put(pos, namesAtPosition);
}
for (String ptmName : tempNames.get(pos)) {
if (!namesAtPosition.contains(ptmName)) {
namesAtPosition.add(ptmName);
}
}
}
}
}
// If a terminal modification cannot be elsewhere lock the terminus
ModificationMatch nTermModification = null;
for (ModificationMatch modMatch : peptide.getModificationMatches()) {
if (modMatch.isVariable() && !modMatch.getTheoreticPtm().equals(PTMFactory.unknownPTM.getName())) {
double refMass = getRefMass(modMatch.getTheoreticPtm(), modificationProfile);
int modSite = modMatch.getModificationSite();
if (modSite == 1) {
ArrayList<String> expectedNamesAtSite = expectedNames.get(modSite);
if (expectedNamesAtSite != null) {
ArrayList<String> filteredNamesAtSite = new ArrayList<String>(expectedNamesAtSite.size());
for (String ptmName : expectedNamesAtSite) {
PTM ptm = ptmFactory.getPTM(ptmName);
if (Math.abs(ptm.getMass() - refMass) < searchParameters.getFragmentIonAccuracy()) {
filteredNamesAtSite.add(ptmName);
}
}
for (String modName : filteredNamesAtSite) {
PTM ptm = ptmFactory.getPTM(modName);
if (ptm.isNTerm()) {
boolean otherPossibleMod = false;
for (String tempName : modificationProfile.getAllNotFixedModifications()) {
if (!tempName.equals(modName)) {
PTM tempPTM = ptmFactory.getPTM(tempName);
if (tempPTM.getMass() == ptm.getMass() && !tempPTM.isNTerm()) {
otherPossibleMod = true;
break;
}
}
}
if (!otherPossibleMod) {
nTermModification = modMatch;
modMatch.setTheoreticPtm(modName);
break;
}
}
}
if (nTermModification != null) {
break;
}
}
}
}
}
ModificationMatch cTermModification = null;
for (ModificationMatch modMatch : peptide.getModificationMatches()) {
if (modMatch.isVariable() && !modMatch.getTheoreticPtm().equals(PTMFactory.unknownPTM.getName()) && modMatch != nTermModification) {
double refMass = getRefMass(modMatch.getTheoreticPtm(), modificationProfile);
int modSite = modMatch.getModificationSite();
if (modSite == peptideSequence.length()) {
ArrayList<String> expectedNamesAtSite = expectedNames.get(modSite);
if (expectedNamesAtSite != null) {
ArrayList<String> filteredNamesAtSite = new ArrayList<String>(expectedNamesAtSite.size());
for (String ptmName : expectedNamesAtSite) {
PTM ptm = ptmFactory.getPTM(ptmName);
if (Math.abs(ptm.getMass() - refMass) < searchParameters.getFragmentIonAccuracy()) {
filteredNamesAtSite.add(ptmName);
}
}
for (String modName : filteredNamesAtSite) {
PTM ptm = ptmFactory.getPTM(modName);
if (ptm.isCTerm()) {
boolean otherPossibleMod = false;
for (String tempName : modificationProfile.getAllNotFixedModifications()) {
if (!tempName.equals(modName)) {
PTM tempPTM = ptmFactory.getPTM(tempName);
if (tempPTM.getMass() == ptm.getMass() && !tempPTM.isCTerm()) {
otherPossibleMod = true;
break;
}
}
}
if (!otherPossibleMod) {
cTermModification = modMatch;
modMatch.setTheoreticPtm(modName);
break;
}
}
}
if (cTermModification != null) {
break;
}
}
}
}
}
// Map the modifications according to search engine localization
HashMap<Integer, ArrayList<String>> siteToPtmMap = new HashMap<Integer, ArrayList<String>>(); // Site to ptm name including termini
HashMap<Integer, ModificationMatch> siteToMatchMap = new HashMap<Integer, ModificationMatch>(); // Site to Modification match excluding termini
HashMap<ModificationMatch, Integer> matchToSiteMap = new HashMap<ModificationMatch, Integer>(); // Modification match to site excluding termini
boolean allMapped = true;
for (ModificationMatch modMatch : peptide.getModificationMatches()) {
boolean mapped = false;
if (modMatch.isVariable() && modMatch != nTermModification && modMatch != cTermModification && !modMatch.getTheoreticPtm().equals(PTMFactory.unknownPTM.getName())) {
double refMass = getRefMass(modMatch.getTheoreticPtm(), modificationProfile);
int modSite = modMatch.getModificationSite();
boolean terminal = false;
ArrayList<String> expectedNamesAtSite = expectedNames.get(modSite);
if (expectedNamesAtSite != null) {
ArrayList<String> filteredNamesAtSite = new ArrayList<String>(expectedNamesAtSite.size());
ArrayList<String> modificationAtSite = siteToPtmMap.get(modSite);
for (String ptmName : expectedNamesAtSite) {
PTM ptm = ptmFactory.getPTM(ptmName);
if (Math.abs(ptm.getMass() - refMass) < searchParameters.getFragmentIonAccuracy()
&& (modificationAtSite == null || !modificationAtSite.contains(ptmName))) {
filteredNamesAtSite.add(ptmName);
}
}
if (filteredNamesAtSite.size() == 1) {
String ptmName = filteredNamesAtSite.get(0);
PTM ptm = ptmFactory.getPTM(ptmName);
if (ptm.isNTerm() && nTermModification == null) {
nTermModification = modMatch;
mapped = true;
} else if (ptm.isCTerm() && cTermModification == null) {
cTermModification = modMatch;
mapped = true;
} else if (!ptm.isNTerm() && !ptm.isCTerm()) {
matchToSiteMap.put(modMatch, modSite);
siteToMatchMap.put(modSite, modMatch);
mapped = true;
}
if (mapped) {
modMatch.setTheoreticPtm(ptmName);
if (modificationAtSite == null) {
modificationAtSite = new ArrayList<String>(2);
siteToPtmMap.put(modSite, modificationAtSite);
}
modificationAtSite.add(ptmName);
}
}
if (!mapped) {
if (filteredNamesAtSite.isEmpty()) {
filteredNamesAtSite = expectedNamesAtSite;
}
if (modSite == 1) {
Double minDiff = null;
String bestPtmName = null;
for (String modName : filteredNamesAtSite) {
PTM ptm = ptmFactory.getPTM(modName);
if (ptm.isNTerm() && nTermModification == null) {
double massError = Math.abs(refMass - ptm.getMass());
if (massError <= searchParameters.getFragmentIonAccuracy()
&& (minDiff == null || massError < minDiff)) {
bestPtmName = modName;
minDiff = massError;
}
}
}
if (bestPtmName != null) {
nTermModification = modMatch;
modMatch.setTheoreticPtm(bestPtmName);
terminal = true;
if (modificationAtSite == null) {
modificationAtSite = new ArrayList<String>(2);
siteToPtmMap.put(modSite, modificationAtSite);
}
modificationAtSite.add(bestPtmName);
mapped = true;
}
} else if (modSite == peptideSequence.length()) {
Double minDiff = null;
String bestPtmName = null;
for (String modName : filteredNamesAtSite) {
PTM ptm = ptmFactory.getPTM(modName);
if (ptm.isCTerm() && cTermModification == null) {
double massError = Math.abs(refMass - ptm.getMass());
if (massError <= searchParameters.getFragmentIonAccuracy()
&& (minDiff == null || massError < minDiff)) {
bestPtmName = modName;
minDiff = massError;
}
}
}
if (bestPtmName != null) {
cTermModification = modMatch;
modMatch.setTheoreticPtm(bestPtmName);
terminal = true;
if (modificationAtSite == null) {
modificationAtSite = new ArrayList<String>(2);
siteToPtmMap.put(modSite, modificationAtSite);
}
modificationAtSite.add(bestPtmName);
mapped = true;
}
}
if (!terminal) {
Double minDiff = null;
String bestPtmName = null;
for (String modName : filteredNamesAtSite) {
PTM ptm = ptmFactory.getPTM(modName);
if (!ptm.isCTerm() && !ptm.isNTerm() && modNames.get(modMatch).contains(modName) && !siteToMatchMap.containsKey(modSite)) {
double massError = Math.abs(refMass - ptm.getMass());
if (massError <= searchParameters.getFragmentIonAccuracy()
&& (minDiff == null || massError < minDiff)) {
bestPtmName = modName;
minDiff = massError;
}
}
}
if (bestPtmName != null) {
modMatch.setTheoreticPtm(bestPtmName);
if (modificationAtSite == null) {
modificationAtSite = new ArrayList<String>(2);
siteToPtmMap.put(modSite, modificationAtSite);
}
modificationAtSite.add(bestPtmName);
matchToSiteMap.put(modMatch, modSite);
siteToMatchMap.put(modSite, modMatch);
mapped = true;
}
}
}
}
}
if (!mapped) {
allMapped = false;
}
}
if (!allMapped) {
// Try to correct incompatible localizations
HashMap<Integer, ArrayList<Integer>> remap = new HashMap<Integer, ArrayList<Integer>>();
for (ModificationMatch modMatch : peptide.getModificationMatches()) {
if (modMatch.isVariable() && modMatch != nTermModification && modMatch != cTermModification && !matchToSiteMap.containsKey(modMatch) && !modMatch.getTheoreticPtm().equals(PTMFactory.unknownPTM.getName())) {
int modSite = modMatch.getModificationSite();
for (int candidateSite : expectedNames.keySet()) {
if (!siteToMatchMap.containsKey(candidateSite)) {
for (String modName : expectedNames.get(candidateSite)) {
if (modNames.get(modMatch).contains(modName)) {
PTM ptm = ptmFactory.getPTM(modName);
if ((!ptm.isCTerm() || cTermModification == null)
&& (!ptm.isNTerm() || nTermModification == null)) {
ArrayList<Integer> ptmSites = remap.get(modSite);
if (ptmSites == null) {
ptmSites = new ArrayList<Integer>(4);
remap.put(modSite, ptmSites);
}