private void ptmSiteInference(SpectrumMatch spectrumMatch, PTMScoringPreferences ptmScoringPreferences, SearchParameters searchParameters, SequenceMatchingPreferences sequenceMatchingPreferences)
throws IOException, IllegalArgumentException, InterruptedException, FileNotFoundException, ClassNotFoundException, SQLException {
Peptide psPeptide = spectrumMatch.getBestPeptideAssumption().getPeptide();
ModificationProfile modificationProfile = searchParameters.getModificationProfile();
PSPtmScores ptmScores = (PSPtmScores) spectrumMatch.getUrParam(new PSPtmScores());
HashMap<Double, ArrayList<ModificationMatch>> modMatchesMap = new HashMap<Double, ArrayList<ModificationMatch>>();
HashMap<Double, HashMap<Integer, String>> possiblePositions = new HashMap<Double, HashMap<Integer, String>>();
for (ModificationMatch modificationMatch : psPeptide.getModificationMatches()) {
if (modificationMatch.isVariable()) {
String modName = modificationMatch.getTheoreticPtm();
PTM ptm = ptmFactory.getPTM(modName);
if (ptm.getType() == PTM.MODAA) {
double ptmMass = ptm.getMass();
ArrayList<ModificationMatch> ptmOccurence = modMatchesMap.get(ptmMass);
if (ptmOccurence == null) {
ptmOccurence = new ArrayList<ModificationMatch>();
modMatchesMap.put(ptmMass, ptmOccurence);
}
ptmOccurence.add(modificationMatch);
HashMap<Integer, String> ptmPossibleSites = possiblePositions.get(ptmMass);
if (ptmPossibleSites == null) {
ptmPossibleSites = new HashMap<Integer, String>();
possiblePositions.put(ptmMass, ptmPossibleSites);
}
for (String similarPtmName : modificationProfile.getSimilarNotFixedModifications(ptmMass)) {
PTM similarPtm = ptmFactory.getPTM(similarPtmName);
for (int pos : psPeptide.getPotentialModificationSites(similarPtm, sequenceMatchingPreferences)) {
ptmPossibleSites.put(pos, similarPtmName);
}
}
} else {
PtmScoring ptmScoring = ptmScores.getPtmScoring(modName);
ptmScoring.setSiteConfidence(modificationMatch.getModificationSite(), PtmScoring.VERY_CONFIDENT);
modificationMatch.setConfident(true);
}
}
}
Set<Double> ptmMasses = modMatchesMap.keySet();
HashMap<Double, HashMap<Double, HashMap<Double, HashMap<Integer, ArrayList<String>>>>> ambiguousScoreToSiteMap = new HashMap<Double, HashMap<Double, HashMap<Double, HashMap<Integer, ArrayList<String>>>>>(ptmMasses.size()); // p score -> d-score -> Map PTM mass -> site -> list of modifications
HashMap<Double, Integer> nRepresentativesMap = new HashMap<Double, Integer>();
for (double ptmMass : ptmMasses) {
ArrayList<ModificationMatch> ptmMatches = modMatchesMap.get(ptmMass);
HashMap<Integer, String> ptmPotentialSites = possiblePositions.get(ptmMass);
HashMap<Integer, String> confidentSites = new HashMap<Integer, String>();
int nPTMs = ptmMatches.size(), nPotentialSites = ptmPotentialSites.size();
if (nPotentialSites < nPTMs) {
throw new IllegalArgumentException("The occurence of modification of mass " + ptmMass + " (" + ptmMatches.size()
+ ") is higher than the number of possible sites (" + ptmPotentialSites.size() + ") on sequence " + psPeptide.getSequence()
+ " in spectrum " + spectrumMatch.getKey() + ".");
} else if (ptmPotentialSites.size() == ptmMatches.size()) {
for (ModificationMatch modMatch : ptmMatches) {
String modName = modMatch.getTheoreticPtm();
int site = modMatch.getModificationSite();
PtmScoring ptmScoring = ptmScores.getPtmScoring(modName);
ptmScoring.setSiteConfidence(site, PtmScoring.VERY_CONFIDENT);
modMatch.setConfident(true);
confidentSites.put(site, modName);
}
} else if (!ptmScoringPreferences.isProbabilitsticScoreCalculation()
|| ptmScoringPreferences.getSelectedProbabilisticScore() == PtmScore.AScore && ptmMatches.size() > 1) {
double pScore = 0; // no probabilistic score in that case
for (ModificationMatch modificationMatch : ptmMatches) {
String modName = modificationMatch.getTheoreticPtm();
PtmScoring ptmScoring = ptmScores.getPtmScoring(modName);
ArrayList<Integer> orderedDSites = new ArrayList<Integer>(ptmScoring.getDSites());
Collections.sort(orderedDSites);
for (int site : orderedDSites) {
if (site == modificationMatch.getModificationSite()) {
double dScore = ptmScoring.getDeltaScore(site);
if (dScore == 0) {
ptmScoring.setSiteConfidence(site, PtmScoring.RANDOM);
modificationMatch.setConfident(false);
} else if (dScore <= 95) {
ptmScoring.setSiteConfidence(site, PtmScoring.DOUBTFUL);
modificationMatch.setConfident(false);
} else {
ptmScoring.setSiteConfidence(site, PtmScoring.CONFIDENT);
modificationMatch.setConfident(true);
confidentSites.put(site, modName);
}
if (!modificationMatch.isConfident()) {
HashMap<Double, HashMap<Double, HashMap<Integer, ArrayList<String>>>> pScoreAmbiguousMap = ambiguousScoreToSiteMap.get(pScore);
if (pScoreAmbiguousMap == null) {
pScoreAmbiguousMap = new HashMap<Double, HashMap<Double, HashMap<Integer, ArrayList<String>>>>(1);
ambiguousScoreToSiteMap.put(pScore, pScoreAmbiguousMap);
}
HashMap<Double, HashMap<Integer, ArrayList<String>>> dScoreAmbiguousMap = pScoreAmbiguousMap.get(dScore);
if (dScoreAmbiguousMap == null) {
dScoreAmbiguousMap = new HashMap<Double, HashMap<Integer, ArrayList<String>>>(nPotentialSites);
pScoreAmbiguousMap.put(dScore, dScoreAmbiguousMap);
}
HashMap<Integer, ArrayList<String>> massAmbiguousMap = dScoreAmbiguousMap.get(ptmMass);
if (massAmbiguousMap == null) {
massAmbiguousMap = new HashMap<Integer, ArrayList<String>>(nPotentialSites);
dScoreAmbiguousMap.put(ptmMass, massAmbiguousMap);
}
ArrayList<String> modifications = massAmbiguousMap.get(site);
if (modifications == null) {
modifications = new ArrayList<String>(1);
massAmbiguousMap.put(site, modifications);
}
modifications.add(modName);
}
}
}
}
} else {
HashMap<Double, HashMap<Double, ArrayList<Integer>>> scoreToSiteMap = new HashMap<Double, HashMap<Double, ArrayList<Integer>>>(nPotentialSites);
for (int site : ptmPotentialSites.keySet()) {
String modName = ptmPotentialSites.get(site);
PtmScoring ptmScoring = ptmScores.getPtmScoring(modName);
double pScore = 0;
double dScore = 0;
if (ptmScoring != null) {
pScore = ptmScoring.getProbabilisticScore(site);
dScore = ptmScoring.getDeltaScore(site);
}
HashMap<Double, ArrayList<Integer>> pScoreMap = scoreToSiteMap.get(pScore);
if (pScoreMap == null) {
pScoreMap = new HashMap<Double, ArrayList<Integer>>(1);
scoreToSiteMap.put(pScore, pScoreMap);
}
ArrayList<Integer> dScoreSites = pScoreMap.get(dScore);
if (dScoreSites == null) {
dScoreSites = new ArrayList<Integer>(1);
pScoreMap.put(dScore, dScoreSites);
}
dScoreSites.add(site);
}
ArrayList<Double> pScores = new ArrayList<Double>(scoreToSiteMap.keySet());
Collections.sort(pScores, Collections.reverseOrder());
int key = spectrumMatch.getBestPeptideAssumption().getIdentificationCharge().value;
TargetDecoyMap currentMap = psmPTMMap.getTargetDecoyMap(ptmMass, key);
if (currentMap == null) {
throw new IllegalArgumentException("No FLR map found for PTM of mass " + ptmMass + " in PSMs of charge " + key + ".");
}
int cpt = 0;
double doubtfulThreshold;
if (ptmScoringPreferences.isEstimateFlr()) {
doubtfulThreshold = -currentMap.getTargetDecoyResults().getScoreLimit();
} else {
doubtfulThreshold = ptmScoringPreferences.getProbabilisticScoreThreshold();
}
double randomThreshold = 0;
if (ptmScoringPreferences.getSelectedProbabilisticScore() == PtmScore.PhosphoRS) {
randomThreshold = (100.0 * nPTMs) / ptmPotentialSites.size();
}
for (Double pScore : pScores) {
HashMap<Double, ArrayList<Integer>> pScoreMap = scoreToSiteMap.get(pScore);
ArrayList<Double> dScores = new ArrayList<Double>(pScoreMap.keySet());
Collections.sort(dScores, Collections.reverseOrder());
for (Double dScore : dScores) {
ArrayList<Integer> sites = pScoreMap.get(dScore);
Collections.sort(sites);
boolean enoughPtms = nPTMs - cpt >= sites.size();
for (int site : sites) {
String modName = ptmPotentialSites.get(site);
PtmScoring ptmScoring = ptmScores.getPtmScoring(modName);
if (ptmScoring == null) {
ptmScoring = new PtmScoring(modName);
ptmScores.addPtmScoring(modName, ptmScoring);
}
ModificationMatch modificationMatch = null;
if (cpt < nPTMs) {
modificationMatch = ptmMatches.get(cpt);
modificationMatch.setModificationSite(site);
modificationMatch.setTheoreticPtm(modName);
}
if (pScore <= randomThreshold || !enoughPtms) {
ptmScoring.setSiteConfidence(site, PtmScoring.RANDOM);
if (modificationMatch != null) {
modificationMatch.setConfident(false);
}
} else if (pScore <= doubtfulThreshold) {
ptmScoring.setSiteConfidence(site, PtmScoring.DOUBTFUL);
if (modificationMatch != null) {
modificationMatch.setConfident(false);
}
} else {
ptmScoring.setSiteConfidence(site, PtmScoring.VERY_CONFIDENT);
if (modificationMatch != null) {
modificationMatch.setConfident(true);
}
confidentSites.put(site, modName);
}
if (modificationMatch == null || !modificationMatch.isConfident()) {
HashMap<Double, HashMap<Double, HashMap<Integer, ArrayList<String>>>> pScoreAmbiguousMap = ambiguousScoreToSiteMap.get(pScore);
if (pScoreAmbiguousMap == null) {
pScoreAmbiguousMap = new HashMap<Double, HashMap<Double, HashMap<Integer, ArrayList<String>>>>(nPotentialSites);
ambiguousScoreToSiteMap.put(pScore, pScoreAmbiguousMap);
}
HashMap<Double, HashMap<Integer, ArrayList<String>>> dScoreAmbiguousMap = pScoreAmbiguousMap.get(dScore);
if (dScoreAmbiguousMap == null) {
dScoreAmbiguousMap = new HashMap<Double, HashMap<Integer, ArrayList<String>>>(1);
pScoreAmbiguousMap.put(dScore, dScoreAmbiguousMap);
}
HashMap<Integer, ArrayList<String>> massAmbiguousMap = dScoreAmbiguousMap.get(ptmMass);
if (massAmbiguousMap == null) {
massAmbiguousMap = new HashMap<Integer, ArrayList<String>>(nPotentialSites);
dScoreAmbiguousMap.put(ptmMass, massAmbiguousMap);
}
ArrayList<String> modifications = massAmbiguousMap.get(site);
if (modifications == null) {
modifications = new ArrayList<String>(1);
massAmbiguousMap.put(site, modifications);
}
modifications.add(modName);
}
cpt++;
}
}
}
}
// Select the best scoring ambiguous sites as representative PTM sites
ArrayList<Integer> ptmConfidentSites = new ArrayList<Integer>(confidentSites.keySet());
for (int site : ptmConfidentSites) {
ptmScores.addConfidentModificationSite(confidentSites.get(site), site);
}
int nConfident = ptmConfidentSites.size();
if (nConfident < nPTMs) {
int nRepresentatives = nPTMs - nConfident;
if (nRepresentatives > 0) {
nRepresentativesMap.put(ptmMass, nRepresentatives);
}
}
}
if (!nRepresentativesMap.isEmpty()) {
HashMap<Double, HashMap<Integer, HashMap<Integer, ArrayList<String>>>> representativeToSecondaryMap = getRepresentativeToSecondaryMap(ambiguousScoreToSiteMap, nRepresentativesMap);
for (Double ptmMass : representativeToSecondaryMap.keySet()) {
HashMap<Integer, HashMap<Integer, ArrayList<String>>> massMap = representativeToSecondaryMap.get(ptmMass);
for (int representativeSite : massMap.keySet()) {
ptmScores.addAmbiguousModificationSites(representativeSite, massMap.get(representativeSite));
}
}
}
}