package com.compomics.util.experiment.identification.ptm.ptmscores; import com.compomics.util.experiment.biology.Ion; import com.compomics.util.experiment.biology.NeutralLoss; import com.compomics.util.experiment.biology.PTM; import com.compomics.util.experiment.biology.Peptide; import com.compomics.util.experiment.biology.ions.PeptideFragmentIon; import com.compomics.util.experiment.identification.spectrum_annotation.NeutralLossesMap; import com.compomics.util.experiment.identification.matches.IonMatch; import com.compomics.util.experiment.identification.matches.ModificationMatch; import com.compomics.util.experiment.identification.spectrum_annotation.spectrum_annotators.PeptideSpectrumAnnotator; import com.compomics.util.experiment.massspectrometry.MSnSpectrum; import com.compomics.util.experiment.massspectrometry.Peak; import com.compomics.util.math.statistics.distributions.BinomialDistribution; import com.compomics.util.experiment.identification.spectrum_annotation.AnnotationSettings; import com.compomics.util.preferences.SequenceMatchingPreferences; import com.compomics.util.experiment.identification.spectrum_annotation.SpecificAnnotationSettings; import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import org.apache.commons.math.MathException; import org.apache.commons.math.util.MathUtils; /** * This class estimates the A-score as described in * http://www.ncbi.nlm.nih.gov/pubmed/16964243 Note: Here the window size is * adapted to mz tolerance and the score is not restricted to phosphorylation. * * @author Marc Vaudel */ public class AScore { /** * Returns the A-score for the best PTM location. In case the two best * locations score the same they are both given with the score of 0. 1 is * the first amino acid. The N-terminus is indexed 0 and the C-terminus with * the peptide length+1. Note that PTMs found on peptides must be loaded in * the PTM factory (com.compomics.util.experiment.biology.PTMFactory), and * if the scoring involves protein terminal PTMs, the protein sequences must * be loaded in the sequence factory * (com.compomics.util.experiment.identification.SequenceFactory) and * indexed using the protein tree (see getDefaultProteinTree in * SequenceFactory). PTMs of same mass should be scored together and given * in the PTMs list. Neutral losses of mass equal to the mass of the PTM * will be ignored. Neutral losses to be accounted for should be given in * the SpecificAnnotationPreferences and will be ignored if * accountNeutralLosses is false. * * @param peptide the peptide of interest * @param ptms the PTMs to score, for instance different phosphorylations * (the PTMs are considered as indistinguishable, i.e. of same mass). * @param spectrum the corresponding spectrum * @param annotationPreferences the global annotation preferences * @param specificAnnotationPreferences the annotation preferences specific * to this peptide and spectrum * @param accountNeutralLosses if false, neutral losses available in the * specific annotation preferences will be ignored * @param sequenceMatchingPreferences the sequence matching preferences for * peptide to protein mapping * @param ptmSequenceMatchingPreferences the sequence matching preferences * for PTM to peptide mapping * @param spectrumAnnotator a spectrum annotator to annotate the spectra * * @return a map containing the best or two best PTM location(s) and the * corresponding A-score * * @throws java.io.IOException exception thrown whenever an error occurred * while reading or writing a file * @throws java.lang.InterruptedException exception thrown whenever a * threading issue occurred while scoring the PTM * @throws java.lang.ClassNotFoundException exception thrown whenever an * error occurred while deserializing an object from the protein tree (the * protein sequence index) * @throws java.sql.SQLException exception thrown whenever an error occurred * while interacting with the protein tree * @throws org.apache.commons.math.MathException exception thrown whenever a * math error occurred while computing the score. */ public static HashMap<Integer, Double> getAScore(Peptide peptide, ArrayList<PTM> ptms, MSnSpectrum spectrum, AnnotationSettings annotationPreferences, SpecificAnnotationSettings specificAnnotationPreferences, boolean accountNeutralLosses, SequenceMatchingPreferences sequenceMatchingPreferences, SequenceMatchingPreferences ptmSequenceMatchingPreferences, PeptideSpectrumAnnotator spectrumAnnotator) throws IOException, InterruptedException, ClassNotFoundException, SQLException, MathException { if (ptms.isEmpty()) { throw new IllegalArgumentException("No PTM given for A-score calculation."); } int nPTM = 0; if (peptide.isModified()) { for (ModificationMatch modMatch : peptide.getModificationMatches()) { if (modMatch.isVariable()) { for (PTM ptm : ptms) { if (ptm.getName().equals(modMatch.getTheoreticPtm())) { nPTM++; } } } } } if (nPTM == 0) { throw new IllegalArgumentException("Given PTMs not found in the peptide for A-score calculation."); } PTM refPTM = ptms.get(0); double ptmMass = refPTM.getMass(); NeutralLossesMap annotationNeutralLosses = specificAnnotationPreferences.getNeutralLossesMap(), scoringLossesMap = new NeutralLossesMap(); if (accountNeutralLosses) { // here annotation should be sequence and modification independant for (String neutralLossName : annotationNeutralLosses.getAccountedNeutralLosses()) { NeutralLoss neutralLoss = NeutralLoss.getNeutralLoss(neutralLossName); if (Math.abs(neutralLoss.getMass() - ptmMass) > specificAnnotationPreferences.getFragmentIonAccuracyInDa(spectrum.getMaxMz())) { scoringLossesMap.addNeutralLoss(neutralLoss, 1, 1); } } } int peptideLength = peptide.getSequence().length(); ArrayList<Integer> possibleSites = new ArrayList<Integer>(); for (PTM ptm : ptms) { if (ptm.isNTerm()) { if (peptide.getPotentialModificationSites(ptm, sequenceMatchingPreferences, ptmSequenceMatchingPreferences).contains(1)) { possibleSites.add(0); } } else if (ptm.isCTerm()) { if (peptide.getPotentialModificationSites(ptm, sequenceMatchingPreferences, ptmSequenceMatchingPreferences).contains(peptideLength)) { possibleSites.add(peptideLength + 1); } } else { for (int potentialSite : peptide.getPotentialModificationSites(ptm, sequenceMatchingPreferences, ptmSequenceMatchingPreferences)) { if (!possibleSites.contains(potentialSite)) { possibleSites.add(potentialSite); } } } } if (possibleSites.size() > nPTM) { Collections.sort(possibleSites); Peptide noModPeptide = Peptide.getNoModPeptide(peptide, ptms); HashMap<Integer, MSnSpectrum> spectrumMap = getReducedSpectra(spectrum, specificAnnotationPreferences.getFragmentIonAccuracyInDa(spectrum.getMaxMz()), 10); HashMap<Integer, HashMap<Integer, Double>> positionToScoreMap = getPositionToScoreMap(peptide, noModPeptide, possibleSites, spectrum, spectrumMap, annotationPreferences, specificAnnotationPreferences, spectrumAnnotator, refPTM); HashMap<Double, ArrayList<Integer>> peptideScoreToPostitionMap = getPeptideScoreToPositionMap(positionToScoreMap); ArrayList<Double> scores = new ArrayList<Double>(peptideScoreToPostitionMap.keySet()); Collections.sort(scores, Collections.reverseOrder()); ArrayList<Integer> bestScoringSites = peptideScoreToPostitionMap.get(scores.get(0)); if (bestScoringSites.size() == 1) { int bestPosition = bestScoringSites.get(0); ArrayList<Integer> secondScoringSites = null; for (int i = 1; i < scores.size() && (secondScoringSites == null || secondScoringSites.isEmpty()); i++) { secondScoringSites = peptideScoreToPostitionMap.get(scores.get(i)); } if (secondScoringSites == null || secondScoringSites.isEmpty()) { throw new IllegalArgumentException("Only one site found in peptide score to position map when estimating the A-score for spectrum " + spectrum.getSpectrumTitle() + " in file " + spectrum.getFileName() + " for modification " + refPTM.getName() + " on peptide " + peptide.getSequence() + "."); } HashMap<Integer, Double> lowestScoreMap = null, tempMap; Double lowestScore = null; for (int secondPosition : secondScoringSites) { int bestDepth = getBestDepth(positionToScoreMap, bestPosition, secondPosition); tempMap = getScoreForPositions(peptide, noModPeptide, refPTM, bestPosition, secondPosition, annotationPreferences, specificAnnotationPreferences, spectrumAnnotator, bestDepth, spectrumMap.get(bestDepth)); Double tempMapLowestScore = null; for (int tempPos : tempMap.keySet()) { double tempScore = tempMap.get(tempPos); if (tempMapLowestScore == null || tempScore < tempMapLowestScore) { tempMapLowestScore = tempScore; } if (tempMapLowestScore == 0.0) { break; } } if (tempMapLowestScore == null) { throw new IllegalArgumentException("No secondary position score found for " + spectrum.getSpectrumTitle() + " in file " + spectrum.getFileName() + " for modification " + refPTM.getName() + " on peptide " + peptide.getSequence() + "."); } if (lowestScore == null || tempMapLowestScore < lowestScore) { lowestScore = tempMapLowestScore; lowestScoreMap = tempMap; } else if (tempMapLowestScore.equals(lowestScore)) { lowestScoreMap.putAll(tempMap); } } if (lowestScoreMap == null) { throw new IllegalArgumentException("No A-score found for " + spectrum.getSpectrumTitle() + " in file " + spectrum.getFileName() + " for modification " + refPTM.getName() + " on peptide " + peptide.getSequence() + "."); } return lowestScoreMap; } else { HashMap<Integer, Double> lowestScoreMap = null, tempMap; Double lowestScore = null; for (int bestPosition : bestScoringSites) { for (int secondPosition : bestScoringSites) { if (bestPosition != secondPosition) { int bestDepth = getBestDepth(positionToScoreMap, bestPosition, secondPosition); tempMap = getScoreForPositions(peptide, noModPeptide, refPTM, bestPosition, secondPosition, annotationPreferences, specificAnnotationPreferences, spectrumAnnotator, bestDepth, spectrumMap.get(bestDepth)); Double tempMapLowestScore = null; for (int tempPos : tempMap.keySet()) { double tempScore = tempMap.get(tempPos); if (tempMapLowestScore == null || tempScore < tempMapLowestScore) { tempMapLowestScore = tempScore; } } if (tempMapLowestScore == null) { throw new IllegalArgumentException("No secondary position score found for " + spectrum.getSpectrumTitle() + " in file " + spectrum.getFileName() + " for modification " + refPTM.getName() + " on peptide " + peptide.getSequence() + "."); } if (lowestScore == null || tempMapLowestScore < lowestScore) { lowestScore = tempMapLowestScore; lowestScoreMap = tempMap; } else if (tempMapLowestScore.equals(lowestScore)) { lowestScoreMap.putAll(tempMap); } } } if (lowestScore == 0.0) { break; } } if (lowestScoreMap == null) { throw new IllegalArgumentException("No A-score found for " + spectrum.getSpectrumTitle() + " in file " + spectrum.getFileName() + " for modification " + refPTM.getName() + " on peptide " + peptide.getSequence() + "."); } return lowestScoreMap; } } else if (possibleSites.size() == nPTM) { HashMap<Integer, Double> result = new HashMap<Integer, Double>(); for (int pos : possibleSites) { result.put(pos, 100.0); } return result; } else { throw new IllegalArgumentException("Found less potential modification sites than PTMs during A-score calculation. Peptide key: " + peptide.getKey()); } } /** * Returns the spectrum depth for two PTM sites which maximizes the score * difference. * * @param positionToScoreMap the position to score map * @param bestPosition the best position * @param secondPosition the second best position * * @return the depth at which the score difference between the best position * and the second position is maximized */ private static int getBestDepth(HashMap<Integer, HashMap<Integer, Double>> positionToScoreMap, int bestPosition, int secondPosition) { Double maxDiff = 0.0; int bestI = 0; for (int i = 1; i <= 10; i++) { double diff = positionToScoreMap.get(bestPosition).get(i) - positionToScoreMap.get(secondPosition).get(i); if (diff > maxDiff) { bestI = i - 1; maxDiff = diff; } } return bestI; } /** * Returns the A-score for two candidate PTM sites in a map: bestSite > * score. If the sites score equally both will be returned in the map. * * @param peptide the peptide of interest * @param noModPeptide the peptide without the variable modification of * interest * @param refPTM the PTM of interest * @param bestPosition the best scoring position * @param secondPosition the second best scoring position * @param annotationPreferences the global annotation preferences * @param specificAnnotationPreferences the annotation preferences specific * to this peptide and spectrum * @param spectrumAnnotator the spectrum annotator which should be used to * annotate the spectrum * @param bestDepth the depth maximizing the score difference between the * best and second best scoring sites (see getBestDepth) * @param spectrumAtBestDepth the spectrum extracted from the original * spectrum filtered at bestDepth intensities * * @return the candidate A-score in a map * * @throws org.apache.commons.math.MathException exception thrown whenever a * math error occurred while computing the score. */ private static HashMap<Integer, Double> getScoreForPositions(Peptide peptide, Peptide noModPeptide, PTM refPTM, int bestPosition, int secondPosition, AnnotationSettings annotationPreferences, SpecificAnnotationSettings specificAnnotationPreferences, PeptideSpectrumAnnotator spectrumAnnotator, int bestDepth, MSnSpectrum spectrumAtBestDepth) throws MathException { HashMap<Integer, Double> result = new HashMap<Integer, Double>(2); int N = 0; int posMin = Math.min(bestPosition, secondPosition); int posMax = Math.max(bestPosition, secondPosition); for (ArrayList<Ion> ions : spectrumAnnotator.getExpectedIons(specificAnnotationPreferences, peptide).values()) { for (Ion ion : ions) { if (ion.getType() == Ion.IonType.PEPTIDE_FRAGMENT_ION) { PeptideFragmentIon fragmentIon = ((PeptideFragmentIon) ion); if (ion.getSubType() == PeptideFragmentIon.A_ION || ion.getSubType() == PeptideFragmentIon.B_ION || ion.getSubType() == PeptideFragmentIon.C_ION) { int aa = fragmentIon.getNumber(); if (aa > posMin && aa <= posMax) { N++; } } else if (ion.getSubType() == PeptideFragmentIon.X_ION || ion.getSubType() == PeptideFragmentIon.Y_ION || ion.getSubType() == PeptideFragmentIon.Z_ION) { int aa = peptide.getSequence().length() - fragmentIon.getNumber(); if (aa > posMin && aa <= posMax) { N++; } } } } } double p = ((double) bestDepth + 1) / 100; Peptide tempPeptide = new Peptide(noModPeptide.getSequence(), noModPeptide.getModificationMatches()); tempPeptide.addModificationMatch(new ModificationMatch(refPTM.getName(), true, posMin)); ArrayList<IonMatch> matches = spectrumAnnotator.getSpectrumAnnotation(annotationPreferences, specificAnnotationPreferences, spectrumAtBestDepth, tempPeptide); int n = 0; for (IonMatch match : matches) { Ion ion = match.ion; if (ion.getType() == Ion.IonType.PEPTIDE_FRAGMENT_ION) { PeptideFragmentIon fragmentIon = ((PeptideFragmentIon) ion); if (ion.getSubType() == PeptideFragmentIon.A_ION || ion.getSubType() == PeptideFragmentIon.B_ION || ion.getSubType() == PeptideFragmentIon.C_ION) { int aa = fragmentIon.getNumber(); if (aa > posMin && aa <= posMax) { n++; } } else if (ion.getSubType() == PeptideFragmentIon.X_ION || ion.getSubType() == PeptideFragmentIon.Y_ION || ion.getSubType() == PeptideFragmentIon.Z_ION) { int aa = peptide.getSequence().length() - fragmentIon.getNumber(); if (aa > posMin && aa <= posMax) { n++; } } } } BinomialDistribution distribution = new BinomialDistribution(N, p); Double p1 = distribution.getDescendingCumulativeProbabilityAt((double) n); tempPeptide = new Peptide(noModPeptide.getSequence(), noModPeptide.getModificationMatches()); tempPeptide.addModificationMatch(new ModificationMatch(refPTM.getName(), true, posMax)); matches = spectrumAnnotator.getSpectrumAnnotation(annotationPreferences, specificAnnotationPreferences, spectrumAtBestDepth, tempPeptide); n = 0; for (IonMatch match : matches) { Ion ion = match.ion; if (ion.getType() == Ion.IonType.PEPTIDE_FRAGMENT_ION) { PeptideFragmentIon fragmentIon = ((PeptideFragmentIon) ion); if (ion.getSubType() == PeptideFragmentIon.A_ION || ion.getSubType() == PeptideFragmentIon.B_ION || ion.getSubType() == PeptideFragmentIon.C_ION) { int aa = fragmentIon.getNumber(); if (aa > posMin && aa <= posMax) { n++; } } else if (ion.getSubType() == PeptideFragmentIon.X_ION || ion.getSubType() == PeptideFragmentIon.Y_ION || ion.getSubType() == PeptideFragmentIon.Z_ION) { int aa = peptide.getSequence().length() - fragmentIon.getNumber(); if (aa > posMin && aa <= posMax) { n++; } } } } Double p2 = distribution.getDescendingCumulativeProbabilityAt((double) n); if (p1.equals(p2)) { result.put(posMin, 0.0); result.put(posMax, 0.0); } else if (p1 < p2) { Double score1; if (p1 == 0.0) { score1 = Double.MAX_VALUE; } else { score1 = -10 * MathUtils.log(10, p1); } Double score2; if (p2 == 0.0) { score2 = Double.MAX_VALUE; } else { score2 = -10 * MathUtils.log(10, p2); } Double score = score1 - score2; result.put(posMin, score); } else { Double score1; if (p1 == 0.0) { score1 = Double.MAX_VALUE; } else { score1 = -10 * MathUtils.log(10, p1); } Double score2; if (p2 == 0.0) { score2 = Double.MAX_VALUE; } else { score2 = -10 * MathUtils.log(10, p2); } Double score = score2 - score1; result.put(posMax, score); } return result; } /** * Estimates the peptide score for every modification localization and * returns a map score > localization. * * @param positionToScoreMap the position to score map * * @return a score to position map */ public static HashMap<Double, ArrayList<Integer>> getPeptideScoreToPositionMap(HashMap<Integer, HashMap<Integer, Double>> positionToScoreMap) { HashMap<Double, ArrayList<Integer>> result = new HashMap<Double, ArrayList<Integer>>(); for (int pos : positionToScoreMap.keySet()) { Double peptideScore = 0.0; Double depthScore = positionToScoreMap.get(pos).get(1); if (depthScore != null) { peptideScore += 0.5 * depthScore; } depthScore = positionToScoreMap.get(pos).get(2); if (depthScore != null) { peptideScore += 0.75 * depthScore; } depthScore = positionToScoreMap.get(pos).get(3); if (depthScore != null) { peptideScore += depthScore; } depthScore = positionToScoreMap.get(pos).get(4); if (depthScore != null) { peptideScore += depthScore; } depthScore = positionToScoreMap.get(pos).get(5); if (depthScore != null) { peptideScore += depthScore; } depthScore = positionToScoreMap.get(pos).get(6); if (depthScore != null) { peptideScore += depthScore; } depthScore = positionToScoreMap.get(pos).get(7); if (depthScore != null) { peptideScore += 0.75 * depthScore; } depthScore = positionToScoreMap.get(pos).get(8); if (depthScore != null) { peptideScore += 0.5 * depthScore; } depthScore = positionToScoreMap.get(pos).get(9); if (depthScore != null) { peptideScore += 0.25 * depthScore; } depthScore = positionToScoreMap.get(pos).get(10); if (depthScore != null) { peptideScore += 0.25 * depthScore; } ArrayList<Integer> sites = result.get(peptideScore); if (sites == null) { sites = new ArrayList<Integer>(2); result.put(peptideScore, sites); } sites.add(pos); } return result; } /** * Returns a map PTM localization > score. * * @param peptide the peptide of interest * @param noModPeptide the peptide without the variable modification of * interest * @param refPTM the PTM of interest * @param annotationPreferences the global annotation preferences * @param specificAnnotationPreferences the annotation preferences specific * to this peptide and spectrum * @param spectrumAnnotator the spectrum annotator which should be used to * annotate the spectrum * @param spectrum the spectrum of interest * @param spectrumMap the map of the extracted spectra: depth > extracted * spectrum * @param possibleSites the possible modification sites * * @return a map PTM localization > score * * @throws org.apache.commons.math.MathException exception thrown whenever a * math error occurred while computing the score. */ public static HashMap<Integer, HashMap<Integer, Double>> getPositionToScoreMap(Peptide peptide, Peptide noModPeptide, ArrayList<Integer> possibleSites, MSnSpectrum spectrum, HashMap<Integer, MSnSpectrum> spectrumMap, AnnotationSettings annotationPreferences, SpecificAnnotationSettings specificAnnotationPreferences, PeptideSpectrumAnnotator spectrumAnnotator, PTM refPTM) throws MathException { HashMap<Integer, HashMap<Integer, Double>> positionToScoreMap = new HashMap<Integer, HashMap<Integer, Double>>(); int N = 0; for (ArrayList<Ion> fragmentIons : spectrumAnnotator.getExpectedIons(specificAnnotationPreferences, peptide).values()) { N += fragmentIons.size(); } String sequence = noModPeptide.getSequence(); int sequenceLength = sequence.length(); for (int i = 0; i < spectrumMap.size(); i++) { double p = ((double) i + 1) / 100; for (int pos : possibleSites) { Peptide tempPeptide = new Peptide(noModPeptide.getSequence(), noModPeptide.getModificationMatches()); int position; if (pos == 0) { position = 1; } else if (pos == sequenceLength + 1) { position = sequenceLength; } else { position = pos; } tempPeptide.addModificationMatch(new ModificationMatch(refPTM.getName(), true, position)); ArrayList<IonMatch> matches = spectrumAnnotator.getSpectrumAnnotation(annotationPreferences, specificAnnotationPreferences, spectrumMap.get(i), tempPeptide); int n = matches.size(); BinomialDistribution distribution = new BinomialDistribution(N, p); Double bigP = distribution.getDescendingCumulativeProbabilityAt((double) n); Double score = -10 * MathUtils.log(10, bigP); HashMap<Integer, Double> scoresAtPosition = positionToScoreMap.get(pos); if (scoresAtPosition == null) { scoresAtPosition = new HashMap<Integer, Double>(2); positionToScoreMap.put(pos, scoresAtPosition); } scoresAtPosition.put(i + 1, score); } } return positionToScoreMap; } /** * Generates a map containing the spectra filtered on intensity with a basis * of 20*m/z tolerance indexed by the depth used. (see A-score paper for * more details). * * @param baseSpectrum the base spectrum * @param mzTolerance the m/z tolerance * * @return a map containing the spectra filtered indexed by peak depth. */ public static HashMap<Integer, MSnSpectrum> getReducedSpectra(MSnSpectrum baseSpectrum, double mzTolerance) { return getReducedSpectra(baseSpectrum, mzTolerance, -1); } /** * Generates a map containing the spectra filtered on intensity with a basis * of 20*m/z tolerance indexed by the depth used. * * @param baseSpectrum the base spectrum * @param mzTolerance the m/z tolerance * @param depthMax the depth to look into (10 for A-score). If -1 the * maximal depth will be used * * @return a map containing the spectra filtered indexed by peak depth. */ public static HashMap<Integer, MSnSpectrum> getReducedSpectra(MSnSpectrum baseSpectrum, double mzTolerance, int depthMax) { HashMap<Integer, MSnSpectrum> result = new HashMap<Integer, MSnSpectrum>(); HashMap<Double, Peak> tempMap, peakMap = baseSpectrum.getPeakMap(); ArrayList<Double> intensities, mz = new ArrayList<Double>(peakMap.keySet()); Collections.sort(mz); double mzMax = mz.get(mz.size() - 1); int cpt = 0; double currentmzMin = 0; while (currentmzMin < mzMax) { int cptTemp = 0; while (cpt < mz.size() && mz.get(cpt) < currentmzMin + 20 * mzTolerance) { cptTemp++; cpt++; } if (depthMax == -1 && cptTemp > depthMax) { depthMax = cptTemp; } currentmzMin += 200 * mzTolerance; } for (int i = 0; i < depthMax; i++) { result.put(i, new MSnSpectrum(2, baseSpectrum.getPrecursor(), baseSpectrum.getSpectrumTitle() + "_" + i, new HashMap<Double, Peak>(), "a score")); } cpt = 0; currentmzMin = 0; while (currentmzMin < mzMax) { intensities = new ArrayList<Double>(); tempMap = new HashMap<Double, Peak>(); while (cpt < mz.size() && mz.get(cpt) < currentmzMin + 20 * mzTolerance) { Peak tempPeak = peakMap.get(mz.get(cpt)); intensities.add(-tempPeak.intensity); tempMap.put(-tempPeak.intensity, tempPeak); cpt++; } Collections.sort(intensities); for (int i = 0; i < intensities.size(); i++) { for (int j = i; j < depthMax; j++) { result.get(j).addPeak(tempMap.get(intensities.get(i))); } } currentmzMin += 200 * mzTolerance; } return result; } }