diff --git a/.gitignore b/.gitignore index e15ab95..7f212dd 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,11 @@ dist/ nbdist/ nbactions.xml nb-configuration.xml +test.msp + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm +*.iml + +## Directory-based project format: +.idea/ diff --git a/pom.xml b/pom.xml index 5ff4934..9856c1b 100644 --- a/pom.xml +++ b/pom.xml @@ -40,8 +40,8 @@ 2.5.1 true - 1.8 - 1.8 + 8 + 8 true true @@ -193,24 +193,29 @@ default - + + netbeans + NetBeans + http://netbeans.apidesign.org/maven2/ + + + Expasy MzJava http://mzjava.expasy.org/maven - - + @@ -240,7 +245,7 @@ com.compomics utilities - 4.11.18 + 5.0.9 commons-math @@ -376,6 +381,12 @@ com.compomics MS2IO 1.1 + + + + + + diff --git a/src/main/java/com/compomics/coss/controller/featureExtraction/DivideAndTopNPeaks.java b/src/main/java/com/compomics/coss/controller/featureExtraction/DivideAndTopNPeaks.java index 4e21a18..48b0aa5 100644 --- a/src/main/java/com/compomics/coss/controller/featureExtraction/DivideAndTopNPeaks.java +++ b/src/main/java/com/compomics/coss/controller/featureExtraction/DivideAndTopNPeaks.java @@ -14,7 +14,8 @@ public class DivideAndTopNPeaks implements Features { // private int topN; - private int windowMassSize = 100; + private int windowMassSize = 10; +// private int windowMassSize = 100; private final Logger LOGGER; // ArrayList cPeaks; // ArrayList filteredPeaks; diff --git a/src/main/java/com/compomics/coss/controller/matching/CosineSimilarity.java b/src/main/java/com/compomics/coss/controller/matching/CosineSimilarity.java index 95f3759..f97ca4e 100644 --- a/src/main/java/com/compomics/coss/controller/matching/CosineSimilarity.java +++ b/src/main/java/com/compomics/coss/controller/matching/CosineSimilarity.java @@ -61,11 +61,14 @@ public double calculateScore(ArrayList expSpec, ArrayList libSpec, i double intScore=-1; try{ intScore=cosineScore(mPeaksExp, mPeaksLib);// * (mPeaksExp.size()/(double)lenA); + }catch(ArithmeticException ex){ System.out.println(ex.toString()); } - double finalScore=intScore*matchedNumPeaks; + + //double finalScore=intScore*matchedNumPeaks; + double finalScore= matchedNumPeaks; //removed intscore for glycan return finalScore; } @@ -90,4 +93,6 @@ private double cosineScore(List v1, List v2) { // parameters vector1 return score; } + + } diff --git a/src/main/java/com/compomics/coss/controller/matching/DataProducer.java b/src/main/java/com/compomics/coss/controller/matching/DataProducer.java index 6caccba..4e9c918 100644 --- a/src/main/java/com/compomics/coss/controller/matching/DataProducer.java +++ b/src/main/java/com/compomics/coss/controller/matching/DataProducer.java @@ -96,7 +96,8 @@ public void run() { expSpec = confData.getExpSpecReader().readAt(confData.getExpSpectraIndex().get(a).getPos()); double mass = expSpec.getPCMass(); - double da_error = mass * this.precTolerance; + //double da_error = mass * this.precTolerance; + double da_error = this.precTolerance; libSpec = confData.getLibSpecReader().readPart(mass, da_error); // synchronized (data) { diff --git a/src/main/java/com/compomics/coss/controller/matching/MSRobin.java b/src/main/java/com/compomics/coss/controller/matching/MSRobin.java index 7e3872a..613cbec 100644 --- a/src/main/java/com/compomics/coss/controller/matching/MSRobin.java +++ b/src/main/java/com/compomics/coss/controller/matching/MSRobin.java @@ -67,7 +67,7 @@ public double calculateScore(ArrayList expSpec, ArrayList libSpec, i sumMatchedIntExp = getSumIntensity(mPeaksExp); sumMatchedIntLib = getSumIntensity(mPeaksLib); - intensity_part = calculateIntensityPart(mPeaksExp, mPeaksLib); + intensity_part = 1;// calculateIntensityPart(mPeaksExp, mPeaksLib); //finalScore = intensity_part * calculateJaccard(matchedNumPeaks, lenA, lenB); finalScore = getfinalScore(totalN, probability, intensity_part); diff --git a/src/main/java/com/compomics/coss/controller/matching/MatchedPeaks.java b/src/main/java/com/compomics/coss/controller/matching/MatchedPeaks.java index f711b80..27224ff 100644 --- a/src/main/java/com/compomics/coss/controller/matching/MatchedPeaks.java +++ b/src/main/java/com/compomics/coss/controller/matching/MatchedPeaks.java @@ -64,7 +64,8 @@ public Map getMatchedPeaks(ArrayList filteredExpMS2_1, ArrayList fil for (int i = 0; i < filteredExpMS2_1.size(); i++) { Peak p1 = filteredExpMS2_1.get(i); double mz_p1 = p1.getMz(); - double diff = fragTolerance;// Based on Da.. not ppm... +// double diff = fragTolerance;// Based on Da.. not ppm... + double diff = mz_p1 * fragTolerance;// Based on PPM! boolean found = false; Peak matchedPeak_2 = null; for (Peak peak_expMS2_2 : filteredExpMS2_2) { diff --git a/src/main/java/com/compomics/coss/view/MainFrame.form b/src/main/java/com/compomics/coss/view/MainFrame.form index f59d0aa..66ed6d9 100644 --- a/src/main/java/com/compomics/coss/view/MainFrame.form +++ b/src/main/java/com/compomics/coss/view/MainFrame.form @@ -137,7 +137,6 @@ - @@ -255,7 +254,7 @@ - + @@ -348,7 +347,6 @@ - @@ -366,7 +364,7 @@ - + @@ -1095,7 +1093,7 @@ - + @@ -1260,7 +1258,7 @@ - + diff --git a/src/main/java/com/compomics/coss/view/MainFrame.java b/src/main/java/com/compomics/coss/view/MainFrame.java index 75330d8..4e16ce9 100644 --- a/src/main/java/com/compomics/coss/view/MainFrame.java +++ b/src/main/java/com/compomics/coss/view/MainFrame.java @@ -127,7 +127,6 @@ private void initComponents() { jMenu4 = new javax.swing.JMenu(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); - setResizable(false); setSize(new java.awt.Dimension(700, 700)); spltPannelBase.setDividerLocation(650); @@ -207,8 +206,7 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { .addGroup(jPanel7Layout.createSequentialGroup() .addComponent(txtfragTolerance, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) - .addComponent(cmbfragmentTolerance, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addComponent(cmbfragmentTolerance, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addGroup(jPanel7Layout.createSequentialGroup() .addComponent(txtprecTolerance, javax.swing.GroupLayout.PREFERRED_SIZE, 49, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(18, 18, 18) @@ -219,7 +217,7 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { jPanel7Layout.setVerticalGroup( jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel7Layout.createSequentialGroup() - .addContainerGap(14, Short.MAX_VALUE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addGroup(jPanel7Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1) .addComponent(txtqueryspec, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) @@ -369,7 +367,7 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { jLayeredPane1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jLayeredPane1Layout.createSequentialGroup() .addGroup(jLayeredPane1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jPanel7, javax.swing.GroupLayout.DEFAULT_SIZE, 627, Short.MAX_VALUE) + .addComponent(jPanel7, javax.swing.GroupLayout.PREFERRED_SIZE, 629, Short.MAX_VALUE) .addGroup(jLayeredPane1Layout.createSequentialGroup() .addGroup(jLayeredPane1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jLayeredPane1Layout.createSequentialGroup() @@ -460,7 +458,7 @@ public void mouseClicked(java.awt.event.MouseEvent evt) { ); jPanel15Layout.setVerticalGroup( jPanel15Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jScrollPane4, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 24, Short.MAX_VALUE) + .addComponent(jScrollPane4, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 24, Short.MAX_VALUE) ); jSplitPane9.setTopComponent(jPanel15); @@ -646,7 +644,7 @@ public void stateChanged(javax.swing.event.ChangeEvent evt) { ); pnlQuerySpecVizLayout.setVerticalGroup( pnlQuerySpecVizLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGap(0, 199, Short.MAX_VALUE) + .addGap(0, 181, Short.MAX_VALUE) ); javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); @@ -682,7 +680,7 @@ public void stateChanged(javax.swing.event.ChangeEvent evt) { .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(txtTotalSpec, javax.swing.GroupLayout.PREFERRED_SIZE, 56, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, Short.MAX_VALUE)))) - .addComponent(pnlQuerySpecViz, javax.swing.GroupLayout.DEFAULT_SIZE, 529, Short.MAX_VALUE) + .addComponent(pnlQuerySpecViz, javax.swing.GroupLayout.DEFAULT_SIZE, 511, Short.MAX_VALUE) ); jPanel3Layout.setVerticalGroup( jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) diff --git a/src/main/java/com/compomics/oglycans/CombinationUtils.java b/src/main/java/com/compomics/oglycans/CombinationUtils.java new file mode 100644 index 0000000..b740ffc --- /dev/null +++ b/src/main/java/com/compomics/oglycans/CombinationUtils.java @@ -0,0 +1,143 @@ +package com.compomics.oglycans; + +import com.compomics.util.experiment.biology.modifications.Modification; +import com.compomics.util.experiment.biology.proteins.Peptide; +import com.compomics.util.experiment.biology.proteins.Protein; +import org.apache.commons.math3.util.CombinatoricsUtils; +import org.apache.log4j.Logger; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +public class CombinationUtils { + + private static final Logger LOGGER = Logger.getLogger(CombinationUtils.class); + + /** + * Calculate the possible modification combinations for the given modification on the given peptide. + * + * @param modification the modification + * @param protein the protein + * @param peptideSequence the peptide sequence + * @return the list of possible modification combinations. Each array has the peptide length + * and contains the modification name on a possible modification site and null anywhere else. + */ + public static List getModificationSiteCombinations(Modification modification, Protein protein, String peptideSequence) { + List modificationSiteCombinations = new ArrayList<>(); + + // create a Peptide object because we're dealing with peptides + Peptide peptide = new Peptide(peptideSequence); + + ArrayList potentialModificationSitesNoCombination = peptide.getPotentialModificationSitesNoCombination(modification, protein.getSequence(), 0); + int[] possibleModificationSites = potentialModificationSitesNoCombination.stream().mapToInt(i -> i).toArray(); + // start from 0 because a variable modification can also not occur + for (int i = 0; i <= potentialModificationSitesNoCombination.size(); i++) { + List possibleModificationSiteCombinations = getCombinationsForModificationOccurrence(peptide.getSequence().length(), modification.getName(), possibleModificationSites, i); + modificationSiteCombinations.addAll(possibleModificationSiteCombinations); + } + + return modificationSiteCombinations; + } + + /** + * Calculate the the possible modification combinations for the given modification occurrence. + * For example 3 possible modification [2, 4, 6] sites and 2 modification occurrences should return + * 3 possible combinations ([2, 4], [2, 6] and [4,6]) as an array of peptide length and the modification name + * on the sites, null otherwise + * + * @param peptideLength the peptide length + * @param modificationName the modification name + * @param possibleModificationSites the array of possible modification sites + * @param numberOfModifications the modification occurrence + * @return the list of possible combinations + */ + public static List getCombinationsForModificationOccurrence(int peptideLength, String modificationName, int[] possibleModificationSites, int numberOfModifications) { + List combinations = new ArrayList<>(); + Iterator iterator = CombinatoricsUtils.combinationsIterator(possibleModificationSites.length, numberOfModifications); + while (iterator.hasNext()) { + int[] combination = iterator.next(); + String[] modificationSitesCombination = new String[peptideLength]; + for (int i = 0; i < combination.length; i++) { + modificationSitesCombination[possibleModificationSites[combination[i]] - 1] = modificationName; + } + combinations.add(modificationSitesCombination); + } + + return combinations; + } + + /** + * For each modification combination in the list, combine it with the other modification combinations. + * For example {[mod1, null, null], [null, mod2, null], [null, null, mod3]} combine to + * {[mod1, mod2, null], [mod1, null, mod3], [null, mod2, mod3]} + * IMPORTANT: no mods on the same location are taken into account for the moment! + * + * @param modificationCombinations the list of modification combinations + * @return the list of combined modification combinations + */ + public static List combineModificationCombinations(List modificationCombinations) { + List combinedModificationCombinations = new ArrayList<>(); + + for (int i = 0; i < modificationCombinations.size(); i++) { + for (int j = i + 1; j < modificationCombinations.size(); j++) { + String[] combinedModificationCombination = new String[modificationCombinations.get(i).length]; + String[] firstModificationCombination = modificationCombinations.get(i); + String[] secondModificationCombination = modificationCombinations.get(j); + for (int k = 0; k < firstModificationCombination.length; k++) { + if (firstModificationCombination[k] != null && secondModificationCombination[k] != null) { + if (!firstModificationCombination[k].equals(secondModificationCombination[k])) { + LOGGER.warn("2 different modifications on the same location"); + } + } + if (firstModificationCombination[k] != null) { + combinedModificationCombination[k] = firstModificationCombination[k]; + } + if (secondModificationCombination[k] != null) { + combinedModificationCombination[k] = secondModificationCombination[k]; + } + } + combinedModificationCombinations.add(combinedModificationCombination); + } + } + return combinedModificationCombinations; + } + + /** + * This method is not used for the moment. + * + * @param firstModificationCombinations + * @param secondModificationCombinations + * @return + */ + public static List combineModificationCombinations(List firstModificationCombinations, List secondModificationCombinations) { + List combinedModificationCombinations = new ArrayList<>(); + + for (String[] firstModificationCombination : firstModificationCombinations) { + for (String[] secondModificationCombination : secondModificationCombinations) { + String[] combinedModificationCombination = new String[firstModificationCombination.length]; + for (int i = 0; i < firstModificationCombination.length; i++) { + if (firstModificationCombination[i] != null && secondModificationCombination[i] != null) { + System.out.println("-----------"); + } + if (firstModificationCombination[i] != null) { + combinedModificationCombination[i] = firstModificationCombination[i]; + } + if (secondModificationCombination[i] != null) { + combinedModificationCombination[i] = secondModificationCombination[i]; + } + } + combinedModificationCombinations.add(combinedModificationCombination); + } + } + + return combinedModificationCombinations; + } + + public static void addArrayToList(List list, String[] candidate) { + if (!list.stream().anyMatch(a -> Arrays.equals(a, candidate))) { + list.add(candidate); + } + } +} diff --git a/src/main/java/com/compomics/oglycans/IonFactory.java b/src/main/java/com/compomics/oglycans/IonFactory.java new file mode 100644 index 0000000..0691195 --- /dev/null +++ b/src/main/java/com/compomics/oglycans/IonFactory.java @@ -0,0 +1,1435 @@ +package com.compomics.oglycans; + +import com.compomics.util.experiment.biology.atoms.Atom; +import com.compomics.util.experiment.biology.ions.Ion; +import com.compomics.util.experiment.biology.ions.NeutralLoss; +import com.compomics.util.experiment.biology.ions.NeutralLossCombination; +import com.compomics.util.experiment.identification.amino_acid_tags.MassGap; +import com.compomics.util.experiment.biology.aminoacids.sequence.AminoAcidSequence; +import com.compomics.util.experiment.biology.aminoacids.AminoAcid; +import com.compomics.util.experiment.biology.proteins.Peptide; +import com.compomics.util.experiment.biology.modifications.ModificationFactory; +import com.compomics.util.experiment.biology.modifications.Modification; +import com.compomics.util.experiment.biology.ions.impl.ImmoniumIon; +import com.compomics.util.experiment.biology.ions.impl.PeptideFragmentIon; +import com.compomics.util.experiment.biology.ions.impl.PrecursorIon; +import com.compomics.util.experiment.biology.ions.impl.RelatedIon; +import com.compomics.util.experiment.biology.ions.impl.ReporterIon; +import com.compomics.util.experiment.biology.ions.impl.TagFragmentIon; +import com.compomics.util.experiment.identification.amino_acid_tags.Tag; +import com.compomics.util.experiment.identification.amino_acid_tags.TagComponent; +import com.compomics.util.parameters.identification.search.ModificationParameters; +import com.compomics.util.experiment.identification.spectrum_annotation.SpecificAnnotationParameters; +import com.compomics.util.experiment.io.biology.protein.SequenceProvider; +import com.compomics.util.experiment.personalization.ExperimentObject; +import com.compomics.util.parameters.identification.advanced.SequenceMatchingParameters; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.stream.Collectors; + +/** + * This factory generates the expected ions from a peptide. + * + * @author Marc Vaudel + * @author Harald Barsnes + */ +public class IonFactory { + + /** + * The instance of the factory. + */ + private static IonFactory instance = null; + /** + * Neutral losses which will be looked for for every peptide independently + * of the modifications found. + */ + private static HashSet defaultNeutralLosses = null; + /** + * Cache for the possible combinations of neutral losses. + */ + private final HashMap neutralLossesCombinationsCache = new HashMap<>(4); + /** + * Cache for the mass of NH3. + */ + private static final double nh3 = Atom.N.getMonoisotopicMass() + 3 * Atom.H.getMonoisotopicMass(); + /** + * Cache for the mass of CO. + */ + private static final double co = Atom.C.getMonoisotopicMass() + Atom.O.getMonoisotopicMass(); + /** + * Cache for the mass of NO. + */ + private static final double nMinusO = Atom.N.getMonoisotopicMass() - Atom.O.getMonoisotopicMass(); + /** + * Cache for the mass of CO2. + */ + private static final double co2 = Atom.C.getMonoisotopicMass() + 2 * Atom.O.getMonoisotopicMass(); + /** + * Cache for the mass of H2. + */ + private static final double h2 = 2 * Atom.H.getMonoisotopicMass(); + /** + * Cache for the mass of H2O. + */ + private static final double h2o = 2 * Atom.H.getMonoisotopicMass() + Atom.O.getMonoisotopicMass(); + /** + * Cache for the mass of HO. + */ + private static final double ho = Atom.H.getMonoisotopicMass() + Atom.O.getMonoisotopicMass(); + + /** + * Constructor. + */ + private IonFactory() { + } + + /** + * Static method which returns the instance of the factory. + * + * @return the instance of the factory + */ + public static IonFactory getInstance() { + if (instance == null) { + instance = new IonFactory(); + } + return instance; + } + + /** + * Returns the default neutral losses. + * + * @return the default neutral losses + */ + public static HashSet getDefaultNeutralLosses() { + if (defaultNeutralLosses == null) { + setDefaultNeutralLosses(); + } + return defaultNeutralLosses; + } + + /** + * Sets the default neutral losses. + */ + private static synchronized void setDefaultNeutralLosses() { + defaultNeutralLosses = new HashSet<>(2); + defaultNeutralLosses.add(NeutralLoss.H2O.name); + defaultNeutralLosses.add(NeutralLoss.NH3.name); + } + + /** + * Returns a list containing the default neutral losses and the losses found + * in the given modifications. Note: modifications must be loaded in the + * modification factory. + * + * @param modificationParameters the modification parameters + * @return the neutral losses expected in the dataset + */ + public static HashSet getNeutralLosses( + ModificationParameters modificationParameters + ) { + + HashSet neutralLosses = new HashSet<>(getDefaultNeutralLosses()); + ModificationFactory modificationFactory = ModificationFactory.getInstance(); + + neutralLosses.addAll(modificationParameters.getAllModifications().stream() + .flatMap(modName -> modificationFactory.getModification(modName).getNeutralLosses().stream()) + .map(neutralLoss -> neutralLoss.name) + .collect(Collectors.toSet())); + + return neutralLosses; + } + + /** + * Returns the reporter ions to annotate with the given PTM settings. + * + * @param modificationParameters the PTMs to annotate + * @return a hashset of the subtype indexes of the reporter ions to annotate + */ + public static HashSet getReporterIons( + ModificationParameters modificationParameters + ) { + + ModificationFactory modificationFactory = ModificationFactory.getInstance(); + + return modificationParameters.getAllModifications().stream() + .flatMap(modName -> modificationFactory.getModification(modName).getReporterIons().stream()) + .map(ReporterIon::getSubType) + .collect(Collectors.toCollection(HashSet::new)); + } + + /** + * This method returns all the theoretic ions expected from a peptide. /!\ + * this method will work only if the modifications found in the peptide are + * in the ModificationFactory. + * + * @param peptide The considered peptide + * @param modificationParameters the modification parameters the + * modification parameters + * @param sequenceProvider a protein sequence provider + * @param modificationsSequenceMatchingParameters the sequence matching + * parameters to use for modifications + * @return the expected fragment ions + */ + public HashMap>> getFragmentIons( + Peptide peptide, + ModificationParameters modificationParameters, + SequenceProvider sequenceProvider, + SequenceMatchingParameters modificationsSequenceMatchingParameters + ) { + return getFragmentIons( + peptide, + null, + modificationParameters, + sequenceProvider, + modificationsSequenceMatchingParameters + ); + } + + /** + * This method returns the theoretic ions expected from a peptide. /!\ this + * method will work only if the modifications found in the peptide are in + * the ModificationFactory. + * + * @param peptide the considered peptide + * @param specificAnnotationSettings if provided, only the ions detectable + * using these settings will be selected + * @param modificationParameters the modification parameters the + * modification parameters + * @param sequenceProvider a protein sequence provider + * @param modificationsSequenceMatchingParameters the sequence matching + * parameters to use for modifications + * @return the expected fragment ions + */ + public HashMap>> getFragmentIons( + Peptide peptide, + SpecificAnnotationParameters specificAnnotationSettings, + ModificationParameters modificationParameters, + SequenceProvider sequenceProvider, + SequenceMatchingParameters modificationsSequenceMatchingParameters + ) { + + HashMap> selectedIonTypes = null; + + if (specificAnnotationSettings != null) { + + selectedIonTypes = specificAnnotationSettings.getIonTypes(); + + } + + HashMap>> result = new HashMap<>(); + String sequence = peptide.getSequence(); + ModificationFactory modificationFactory = ModificationFactory.getInstance(); + + HashSet possibleNeutralLosses = null; + + if (specificAnnotationSettings == null || !specificAnnotationSettings.getNeutralLossesMap().isEmpty()) { + + possibleNeutralLosses = new HashSet<>(getDefaultNeutralLosses()); + + } + + HashSet allModifications = new HashSet<>(1); + + String[] variableModNames = null; + + // @TODO: quick fix that ought to be replaced when the ptm scoring code had been rewritten + try { + variableModNames = peptide.getIndexedVariableModifications(); + } catch (IllegalArgumentException e) { + // illegal peptide, i.e. more than one modification on the same site + return result; + } + + Modification[] variableModifications = new Modification[variableModNames.length]; + + String[] fixedModNames = peptide.getFixedModifications( + modificationParameters, + sequenceProvider, + modificationsSequenceMatchingParameters + ); + Modification[] fixedModifications = new Modification[fixedModNames.length]; + + for (int i = 0; i < variableModNames.length; i++) { + + String modName = variableModNames[i]; + + if (modName != null) { + + allModifications.add(modName); + Modification modification = modificationFactory.getModification(modName); + variableModifications[i] = modification; + + } + + modName = fixedModNames[i]; + + if (modName != null) { + + allModifications.add(modName); + Modification modification = modificationFactory.getModification(modName); + fixedModifications[i] = modification; + + } + } + + for (String modName : allModifications) { + + Modification modification = modificationFactory.getModification(modName); + + if (selectedIonTypes == null || selectedIonTypes.keySet().contains(Ion.IonType.REPORTER_ION)) { + + for (ReporterIon reporterIon : modification.getReporterIons()) { + + HashMap> ionsMap = result.get(Ion.IonType.REPORTER_ION.index); + + if (ionsMap == null) { + + ionsMap = new HashMap<>(modification.getReporterIons().size()); + result.put(Ion.IonType.REPORTER_ION.index, ionsMap); + + } + + int subType = reporterIon.getSubType(); + ArrayList ions = ionsMap.get(subType); + + if (ions == null) { + + ions = new ArrayList<>(1); + ionsMap.put(subType, ions); + ions.add(reporterIon); + + } + } + } + + if (specificAnnotationSettings == null || !specificAnnotationSettings.getNeutralLossesMap().isEmpty()) { + + for (NeutralLoss neutralLoss : modification.getNeutralLosses()) { + + possibleNeutralLosses.add(neutralLoss.name); + + } + } + } + + // We account for up to two neutral losses per ion maximum + NeutralLossCombination[] neutralLossesCombinations = null; + + if (specificAnnotationSettings == null || !specificAnnotationSettings.getNeutralLossesMap().isEmpty()) { + + neutralLossesCombinations = getNeutralLossesCombinations(possibleNeutralLosses); + + } + + double forwardMass = 0; + double bForwardMass = 0; + + Modification modification = fixedModifications[0]; + + if (modification != null) { + + forwardMass += modification.getMass(); + bForwardMass += modification.getMass(); + + } + + modification = variableModifications[0]; + + if (modification != null) { + + forwardMass += modification.getMass(); + if(!modification.getName().equals("oglycans")){ + bForwardMass += modification.getMass(); + } + + } + + double rewindMass = Atom.O.getMonoisotopicMass(); + double yRewindMass = rewindMass; + + modification = fixedModifications[sequence.length() + 1]; + + if (modification != null) { + + rewindMass += modification.getMass(); + yRewindMass += modification.getMass(); + } + + modification = variableModifications[sequence.length() + 1]; + + if (modification != null) { + + rewindMass += modification.getMass(); + if(!modification.getName().equals("oglycans")){ + yRewindMass += modification.getMass(); + } + + } + + for (int aa = 0; aa < sequence.length() - 1; aa++) { + + char aaName = sequence.charAt(aa); + + // immonium ions + if (selectedIonTypes == null || selectedIonTypes.keySet().contains(Ion.IonType.IMMONIUM_ION)) { + + HashMap> ionsMap = result.get(Ion.IonType.IMMONIUM_ION.index); + + if (ionsMap == null) { + + ionsMap = new HashMap<>(sequence.length()); + result.put(Ion.IonType.IMMONIUM_ION.index, ionsMap); + + } + + ImmoniumIon immoniumIon = ImmoniumIon.getImmoniumIon(aaName); + int subType = immoniumIon.getSubType(); + ArrayList ions = ionsMap.get(subType); + + if (ions == null) { + + ions = new ArrayList<>(1); + ions.add(immoniumIon); + ionsMap.put(subType, ions); + + } + } + + // related ions + if (selectedIonTypes == null || selectedIonTypes.keySet().contains(Ion.IonType.RELATED_ION)) { + + HashMap> ionsMap = result.get(Ion.IonType.RELATED_ION.index); + + if (ionsMap == null) { + + ionsMap = new HashMap<>(sequence.length()); + result.put(Ion.IonType.RELATED_ION.index, ionsMap); + + } + + ArrayList relatedIons = RelatedIon.getRelatedIons(AminoAcid.getAminoAcid(aaName)); + + if (relatedIons != null) { + + for (RelatedIon tempRelated : relatedIons) { + + int subType = tempRelated.getSubType(); + + ArrayList ions = ionsMap.get(subType); + + if (ions == null) { + + ions = new ArrayList<>(1); + + } + + ions.add(tempRelated); + ionsMap.put(subType, ions); + + } + } + } + + int faa = aa + 1; + AminoAcid currentAA = AminoAcid.getAminoAcid(aaName); + forwardMass += currentAA.getMonoisotopicMass(); + bForwardMass += currentAA.getMonoisotopicMass(); + + modification = fixedModifications[faa]; + + if (modification != null) { + + forwardMass += modification.getMass(); + + } + + modification = variableModifications[faa]; + + if (modification != null) { + + forwardMass += modification.getMass(); + if(!modification.getName().equals("oglycans")){ + bForwardMass += modification.getMass(); + } + } + + HashMap> ionsMap = result.get(Ion.IonType.PEPTIDE_FRAGMENT_ION.index); + + if (ionsMap == null) { + + ionsMap = new HashMap<>(6); + result.put(Ion.IonType.PEPTIDE_FRAGMENT_ION.index, ionsMap); + + } + + if (specificAnnotationSettings == null || selectedIonTypes.keySet().contains(Ion.IonType.PEPTIDE_FRAGMENT_ION) && specificAnnotationSettings.getFragmentIonTypes().contains(PeptideFragmentIon.A_ION)) { + + // add the a-ions + int subType = PeptideFragmentIon.A_ION; + ArrayList ions = ionsMap.get(subType); + + if (ions == null) { + + if (neutralLossesCombinations != null) { + + ions = new ArrayList<>(neutralLossesCombinations.length); + + } else { + + ions = new ArrayList<>(1); + + } + + ionsMap.put(subType, ions); + + } + + if (neutralLossesCombinations != null) { + + for (NeutralLossCombination losses : neutralLossesCombinations) { + + ions.add(new PeptideFragmentIon(subType, faa, forwardMass - co - losses.getMass(), losses.getNeutralLossCombination())); + + } + + } else { + + ions.add(new PeptideFragmentIon(subType, faa, forwardMass - co, null)); + + } + } + + if (specificAnnotationSettings == null || selectedIonTypes.keySet().contains(Ion.IonType.PEPTIDE_FRAGMENT_ION) && specificAnnotationSettings.getFragmentIonTypes().contains(PeptideFragmentIon.B_ION)) { + + // add the b-ions + int subType = PeptideFragmentIon.B_ION; + ArrayList ions = ionsMap.get(subType); + + if (ions == null) { + + if (neutralLossesCombinations != null) { + + ions = new ArrayList<>(neutralLossesCombinations.length); + + } else { + + ions = new ArrayList<>(1); + } + + ionsMap.put(subType, ions); + + } + + if (neutralLossesCombinations != null) { + + for (NeutralLossCombination losses : neutralLossesCombinations) { + + ions.add(new PeptideFragmentIon(subType, faa, bForwardMass - losses.getMass(), losses.getNeutralLossCombination())); + + } + } else { + + ions.add(new PeptideFragmentIon(subType, faa, bForwardMass, null)); + + } + } + + if (specificAnnotationSettings == null || selectedIonTypes.keySet().contains(Ion.IonType.PEPTIDE_FRAGMENT_ION) && specificAnnotationSettings.getFragmentIonTypes().contains(PeptideFragmentIon.C_ION)) { + + // add the c-ion + int subType = PeptideFragmentIon.C_ION; + ArrayList ions = ionsMap.get(subType); + + if (ions == null) { + + if (neutralLossesCombinations != null) { + + ions = new ArrayList<>(neutralLossesCombinations.length); + + } else { + + ions = new ArrayList<>(1); + + } + + ionsMap.put(subType, ions); + + } + + if (neutralLossesCombinations != null) { + + for (NeutralLossCombination losses : neutralLossesCombinations) { + + ions.add(new PeptideFragmentIon(subType, faa, forwardMass + nh3 - losses.getMass(), losses.getNeutralLossCombination())); + + } + + } else { + + ions.add(new PeptideFragmentIon(subType, faa, forwardMass + nh3, null)); + + } + } + + int raa = sequence.length() - aa - 1; + currentAA = AminoAcid.getAminoAcid(sequence.charAt(raa)); + rewindMass += currentAA.getMonoisotopicMass(); + yRewindMass += currentAA.getMonoisotopicMass(); + + modification = fixedModifications[raa + 1]; + + if (modification != null) { + + rewindMass += modification.getMass(); + yRewindMass += modification.getMass(); + } + + modification = variableModifications[raa + 1]; + + if (modification != null) { + + rewindMass += modification.getMass(); + if(!modification.getName().equals("oglycans")){ + yRewindMass += modification.getMass(); + } + } + + if (specificAnnotationSettings == null || selectedIonTypes.keySet().contains(Ion.IonType.PEPTIDE_FRAGMENT_ION) && specificAnnotationSettings.getFragmentIonTypes().contains(PeptideFragmentIon.X_ION)) { + + // add the x-ion + int subType = PeptideFragmentIon.X_ION; + ArrayList ions = ionsMap.get(subType); + + if (ions == null) { + + if (neutralLossesCombinations != null) { + + ions = new ArrayList<>(neutralLossesCombinations.length); + + } else { + + ions = new ArrayList<>(1); + + } + + ionsMap.put(subType, ions); + + } + + if (neutralLossesCombinations != null) { + + for (NeutralLossCombination losses : neutralLossesCombinations) { + + ions.add(new PeptideFragmentIon(subType, faa, rewindMass + co - losses.getMass(), losses.getNeutralLossCombination())); + + } + } else { + + ions.add(new PeptideFragmentIon(subType, faa, rewindMass + co, null)); + + } + } + + if (specificAnnotationSettings == null || selectedIonTypes.keySet().contains(Ion.IonType.PEPTIDE_FRAGMENT_ION) && specificAnnotationSettings.getFragmentIonTypes().contains(PeptideFragmentIon.Y_ION)) { + + // add the y-ions + int subType = PeptideFragmentIon.Y_ION; + ArrayList ions = ionsMap.get(subType); + + if (ions == null) { + + if (neutralLossesCombinations != null) { + + ions = new ArrayList<>(neutralLossesCombinations.length); + + } else { + + ions = new ArrayList<>(1); + + } + + ionsMap.put(subType, ions); + + } + + if (neutralLossesCombinations != null) { + + for (NeutralLossCombination losses : neutralLossesCombinations) { + + ions.add(new PeptideFragmentIon(subType, faa, yRewindMass + h2 - losses.getMass(), losses.getNeutralLossCombination())); + + } + + } else { + + ions.add(new PeptideFragmentIon(subType, faa, yRewindMass + h2, null)); + + } + } + + if (specificAnnotationSettings == null || selectedIonTypes.keySet().contains(Ion.IonType.PEPTIDE_FRAGMENT_ION) && specificAnnotationSettings.getFragmentIonTypes().contains(PeptideFragmentIon.Z_ION)) { + + // add the z-ions + int subType = PeptideFragmentIon.Z_ION; + ArrayList ions = ionsMap.get(subType); + + if (ions == null) { + + if (neutralLossesCombinations != null) { + + ions = new ArrayList<>(neutralLossesCombinations.length); + + } else { + + ions = new ArrayList<>(1); + + } + + ionsMap.put(subType, ions); + + } + + if (neutralLossesCombinations != null) { + + for (NeutralLossCombination losses : neutralLossesCombinations) { + + ions.add(new PeptideFragmentIon(subType, faa, rewindMass - Atom.N.getMonoisotopicMass() - losses.getMass(), losses.getNeutralLossCombination())); + + } + + // add the z + 1 and z + 2 fragment ions + ions.add(new PeptideFragmentIon(subType, faa, rewindMass - Atom.N.getMonoisotopicMass() + Atom.H.getMonoisotopicMass(), null)); + ions.add(new PeptideFragmentIon(subType, faa, rewindMass - Atom.N.getMonoisotopicMass() + 2 * Atom.H.getMonoisotopicMass(), null)); + + + } else { + + ions.add(new PeptideFragmentIon(subType, faa, rewindMass - Atom.N.getMonoisotopicMass(), null)); + + } + } + } + + AminoAcid currentAA = AminoAcid.getAminoAcid(sequence.charAt(sequence.length() - 1)); + forwardMass += currentAA.getMonoisotopicMass(); + + modification = fixedModifications[sequence.length()]; + + if (modification != null) { + + forwardMass += modification.getMass(); + + } + + modification = variableModifications[sequence.length()]; + + if (modification != null) { + + forwardMass += modification.getMass(); + + } + + modification = fixedModifications[sequence.length() + 1]; + + if (modification != null) { + + forwardMass += modification.getMass(); + + } + + modification = variableModifications[sequence.length() + 1]; + + if (modification != null) { + + forwardMass += modification.getMass(); + + } + + if (specificAnnotationSettings == null || selectedIonTypes.keySet().contains(Ion.IonType.PRECURSOR_ION)) { + + // add the precursor ion + HashMap> ionsMap = result.get(Ion.IonType.PRECURSOR_ION.index); + + if (ionsMap == null) { + + ionsMap = new HashMap<>(1); + result.put(Ion.IonType.PRECURSOR_ION.index, ionsMap); + + } + + int subType = PrecursorIon.PRECURSOR; + ArrayList ions = ionsMap.get(subType); + + if (ions == null) { + + if (neutralLossesCombinations != null) { + + ions = new ArrayList<>(neutralLossesCombinations.length); + + } else { + + ions = new ArrayList<>(1); + + } + + ionsMap.put(subType, ions); + + } + + if (neutralLossesCombinations != null) { + + for (NeutralLossCombination losses : neutralLossesCombinations) { + + ions.add(new PrecursorIon(forwardMass + h2o - losses.getMass(), losses.getNeutralLossCombination())); + + } + + // Add the precursor peak - oglycans + ions.add(new PrecursorIon(forwardMass + h2o - Playground.oglycan.getMass(), null)); + // Add the precursor peak + 1 + ions.add(new PrecursorIon(forwardMass + h2o + Atom.H.getMonoisotopicMass(), null)); + // Add the precursor peak - oglycans + ions.add(new PrecursorIon(forwardMass + h2o + 2 * Atom.H.getMonoisotopicMass(), null)); + + } else { + + ions.add(new PrecursorIon(forwardMass + ho, null)); + + } + } + + return result; + } + + /** + * This method returns the theoretic ions expected from a tag. + *

+ * /!\ this method will work only if the PTMs found in the tag are in the + * PTMFactory. + * + * @param tag the considered tag + * @param modificationParameters the modification parameters the + * modification parameters + * @param modificationsSequenceMatchingParameters the sequence matching + * parameters to use for modifications + * @return the expected fragment ions + */ + public HashMap>> getFragmentIons( + Tag tag, + ModificationParameters modificationParameters, + SequenceMatchingParameters modificationsSequenceMatchingParameters + ) { + + ModificationFactory modificationFactory = ModificationFactory.getInstance(); + + HashMap>> result = new HashMap<>(); + HashSet possibleNeutralLosses = new HashSet<>(getDefaultNeutralLosses()); + + // We account for up to two neutral losses per ion maximum + NeutralLossCombination[] neutralLossesCombinations = getNeutralLossesCombinations(possibleNeutralLosses); + + HashSet allModifications = new HashSet<>(2); + + int ionNumberOffset = 1; + ArrayList massOffsets = new ArrayList<>(); + massOffsets.add(0.0); + + ArrayList tagContent = tag.getContent(); + + for (int tagIndex = 0; tagIndex < tagContent.size(); tagIndex++) { + + TagComponent tagComponent = tagContent.get(tagIndex); + + if (tagComponent instanceof AminoAcidSequence) { + + AminoAcidSequence aminoAcidSequence = (AminoAcidSequence) tagComponent; + double sequenceMass = 0; + + String[] variableModNames = aminoAcidSequence.getIndexedVariableModifications(); + String[] fixedModNames = aminoAcidSequence.getFixedModifications(tagIndex == 0, tagIndex == tagContent.size() - 1, modificationParameters, modificationsSequenceMatchingParameters); + + HashSet newModifications = new HashSet<>(0); + Modification[] variableModifications = new Modification[variableModNames.length]; + Modification[] fixedModifications = new Modification[fixedModNames.length]; + + for (int i = 0; i < variableModifications.length; i++) { + + String modName = variableModNames[i]; + + if (modName != null) { + + if (!allModifications.contains(modName)) { + newModifications.add(modName); + allModifications.add(modName); + } + + Modification modification = modificationFactory.getModification(modName); + variableModifications[i] = modification; + + } + + modName = fixedModNames[i]; + + if (modName != null) { + + if (!allModifications.contains(modName)) { + newModifications.add(modName); + allModifications.add(modName); + } + + Modification modification = modificationFactory.getModification(modName); + fixedModifications[i] = modification; + + } + } + + for (String modName : newModifications) { + + Modification modification = ModificationFactory.getInstance().getModification(modName); + + for (ReporterIon ptmReporterIon : modification.getReporterIons()) { + HashMap> ionsMap = result.get(Ion.IonType.REPORTER_ION.index); + if (ionsMap == null) { + ionsMap = new HashMap<>(1); + result.put(Ion.IonType.REPORTER_ION.index, ionsMap); + } + int subType = ptmReporterIon.getSubType(); + ArrayList ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(1); + ionsMap.put(subType, ions); + ions.add(ptmReporterIon); + } + } + for (NeutralLoss neutralLoss : modification.getNeutralLosses()) { + possibleNeutralLosses.add(neutralLoss.name); + } + } + + for (int i = 0; i < aminoAcidSequence.length(); i++) { + + AminoAcid aminoAcid = aminoAcidSequence.getAminoAcidAt(i); + + // immonium ions + HashMap> ionsMap = result.get(Ion.IonType.IMMONIUM_ION.index); + if (ionsMap == null) { + ionsMap = new HashMap<>(1); + result.put(Ion.IonType.IMMONIUM_ION.index, ionsMap); + } + ImmoniumIon immoniumIon = ImmoniumIon.getImmoniumIon(aminoAcid.getSingleLetterCodeAsChar()); + int subType = immoniumIon.getSubType(); + ArrayList ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(1); + ions.add(immoniumIon); + ionsMap.put(subType, ions); + } + + // related ions + ionsMap = result.get(Ion.IonType.RELATED_ION.index); + if (ionsMap == null) { + ionsMap = new HashMap<>(1); + result.put(Ion.IonType.RELATED_ION.index, ionsMap); + } + ArrayList relatedIons = RelatedIon.getRelatedIons(aminoAcid); + + if (relatedIons != null) { + for (RelatedIon tempRelated : relatedIons) { + subType = tempRelated.getSubType(); + + ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(1); + } + + ions.add(tempRelated); + ionsMap.put(subType, ions); + } + } + + double mass = aminoAcid.getMonoisotopicMass(); + + Modification modification = variableModifications[i]; + + if (modification != null) { + mass += modification.getMass(); + } + + modification = fixedModifications[i]; + + if (modification != null) { + mass += modification.getMass(); + } + + sequenceMass += mass; + + ionsMap = result.get(Ion.IonType.TAG_FRAGMENT_ION.index); + if (ionsMap == null) { + ionsMap = new HashMap<>(); + result.put(Ion.IonType.TAG_FRAGMENT_ION.index, ionsMap); + } + for (double massOffset : massOffsets) { + int aa = ionNumberOffset + i; + int subaa = i + 1; + double forwardMass = massOffset + sequenceMass; + + // add the a-ions + subType = TagFragmentIon.A_ION; + ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(); + ionsMap.put(subType, ions); + } + for (NeutralLossCombination losses : neutralLossesCombinations) { + ions.add(new TagFragmentIon(subType, aa, subaa, forwardMass - co - losses.getMass(), losses.getNeutralLossCombination(), massOffset)); + } + + // add the b-ions + subType = TagFragmentIon.B_ION; + ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(); + ionsMap.put(subType, ions); + } + for (NeutralLossCombination losses : neutralLossesCombinations) { + ions.add(new TagFragmentIon(subType, aa, subaa, forwardMass - losses.getMass(), losses.getNeutralLossCombination(), massOffset)); + } + + // add the c-ion + subType = TagFragmentIon.C_ION; + ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(); + ionsMap.put(subType, ions); + } + for (NeutralLossCombination losses : neutralLossesCombinations) { + ions.add(new TagFragmentIon(subType, aa, subaa, forwardMass + nh3 - losses.getMass(), losses.getNeutralLossCombination(), massOffset)); + } + } + } + ArrayList newOffsetMasses = new ArrayList<>(); + for (double offsetMass : massOffsets) { + double newMass = offsetMass + sequenceMass; + if (!newOffsetMasses.contains(newMass)) { + newOffsetMasses.add(newMass); + } + } + massOffsets = newOffsetMasses; + ionNumberOffset += aminoAcidSequence.length(); + } else if (tagComponent instanceof MassGap) { + double gapMass = tagComponent.getMass(); + int aa = ionNumberOffset; + int subaa = 0; + + HashMap> ionsMap = result.get(Ion.IonType.TAG_FRAGMENT_ION.index); + if (ionsMap == null) { + ionsMap = new HashMap<>(); + result.put(Ion.IonType.TAG_FRAGMENT_ION.index, ionsMap); + } + + for (double massOffset : massOffsets) { + double forwardMass = massOffset + gapMass; + + // add the a-ions + int subType = TagFragmentIon.A_ION; + ArrayList ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(); + ionsMap.put(subType, ions); + } + for (NeutralLossCombination losses : neutralLossesCombinations) { + ions.add(new TagFragmentIon(subType, aa, subaa, forwardMass - co - losses.getMass(), losses.getNeutralLossCombination(), massOffset)); + } + + // add the b-ions + subType = TagFragmentIon.B_ION; + ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(); + ionsMap.put(subType, ions); + } + for (NeutralLossCombination losses : neutralLossesCombinations) { + ions.add(new TagFragmentIon(subType, aa, subaa, forwardMass - losses.getMass(), losses.getNeutralLossCombination(), massOffset)); + } + + // add the c-ion + subType = TagFragmentIon.C_ION; + ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(); + ionsMap.put(subType, ions); + } + for (NeutralLossCombination losses : neutralLossesCombinations) { + ions.add(new TagFragmentIon(subType, aa, subaa, forwardMass + nh3 - losses.getMass(), losses.getNeutralLossCombination(), massOffset)); + } + + } + ArrayList newOffsetMasses = new ArrayList<>(); + for (double offsetMass : massOffsets) { + newOffsetMasses.add(offsetMass + gapMass); + } + massOffsets = newOffsetMasses; + ionNumberOffset++; + } else { + throw new UnsupportedOperationException("Fragment ion not implemented for tag component " + tagComponent.getClass() + "."); + } + } + + ArrayList reversedTag = new ArrayList<>(tag.getContent()); + Collections.reverse(reversedTag); + ionNumberOffset = 0; + massOffsets.clear(); + massOffsets.add(0.0); + allModifications.clear(); + possibleNeutralLosses.clear(); + + for (int tagIndex = 0; tagIndex < tagContent.size(); tagIndex++) { + + TagComponent tagComponent = tagContent.get(tagIndex); + + if (tagComponent instanceof AminoAcidSequence) { + + AminoAcidSequence aminoAcidSequence = (AminoAcidSequence) tagComponent; + double sequenceMass = 0; + + String[] variableModNames = aminoAcidSequence.getIndexedVariableModifications(); + String[] fixedModNames = aminoAcidSequence.getFixedModifications(tagIndex == 0, tagIndex == tagContent.size() - 1, modificationParameters, modificationsSequenceMatchingParameters); + + HashSet newModifications = new HashSet<>(0); + Modification[] variableModifications = new Modification[variableModNames.length]; + Modification[] fixedModifications = new Modification[fixedModNames.length]; + + for (int i = 0; i < variableModifications.length; i++) { + + String modName = variableModNames[i]; + + if (modName != null) { + + if (!allModifications.contains(modName)) { + newModifications.add(modName); + allModifications.add(modName); + } + + Modification modification = modificationFactory.getModification(modName); + variableModifications[i] = modification; + + } + + modName = fixedModNames[i]; + + if (modName != null) { + + if (!allModifications.contains(modName)) { + newModifications.add(modName); + allModifications.add(modName); + } + + Modification modification = modificationFactory.getModification(modName); + fixedModifications[i] = modification; + + } + } + + for (String modName : newModifications) { + + Modification modification = ModificationFactory.getInstance().getModification(modName); + for (NeutralLoss neutralLoss : modification.getNeutralLosses()) { + possibleNeutralLosses.add(neutralLoss.name); + } + } + + for (int i = aminoAcidSequence.length() - 1; i >= 0; i--) { + + AminoAcid aminoAcid = aminoAcidSequence.getAminoAcidAt(i); + + // immonium ions + HashMap> ionsMap = result.get(Ion.IonType.IMMONIUM_ION.index); + if (ionsMap == null) { + ionsMap = new HashMap<>(); + result.put(Ion.IonType.IMMONIUM_ION.index, ionsMap); + } + ImmoniumIon immoniumIon = ImmoniumIon.getImmoniumIon(aminoAcid.getSingleLetterCodeAsChar()); + int subType = immoniumIon.getSubType(); + ArrayList ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(); + ions.add(immoniumIon); + ionsMap.put(subType, ions); + } + + // related ions + ionsMap = result.get(Ion.IonType.RELATED_ION.index); + if (ionsMap == null) { + ionsMap = new HashMap<>(); + result.put(Ion.IonType.RELATED_ION.index, ionsMap); + } + ArrayList relatedIons = RelatedIon.getRelatedIons(aminoAcid); + + if (relatedIons != null) { + for (RelatedIon tempRelated : relatedIons) { + subType = tempRelated.getSubType(); + + ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(1); + } + + ions.add(tempRelated); + ionsMap.put(subType, ions); + } + } + + double mass = aminoAcid.getMonoisotopicMass(); + + Modification modification = variableModifications[i]; + + if (modification != null) { + mass += modification.getMass(); + } + + modification = fixedModifications[i]; + + if (modification != null) { + mass += modification.getMass(); + } + + sequenceMass += mass; + + ionsMap = result.get(Ion.IonType.TAG_FRAGMENT_ION.index); + if (ionsMap == null) { + ionsMap = new HashMap<>(); + result.put(Ion.IonType.TAG_FRAGMENT_ION.index, ionsMap); + } + for (double massOffset : massOffsets) { + int aa = ionNumberOffset + aminoAcidSequence.length() - i; + int subaa = aminoAcidSequence.length() - i; + double rewindMass = massOffset + sequenceMass; + double gap = 0; + if (massOffset != Atom.O.getMonoisotopicMass()) { + gap = massOffset; + } + + // add the x-ions + subType = TagFragmentIon.X_ION; + ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(); + ionsMap.put(subType, ions); + } + for (NeutralLossCombination losses : neutralLossesCombinations) { + ions.add(new TagFragmentIon(subType, aa, subaa, rewindMass + co2 - losses.getMass(), losses.getNeutralLossCombination(), gap)); + } + + // add the y-ions + subType = TagFragmentIon.Y_ION; + ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(); + ionsMap.put(subType, ions); + } + for (NeutralLossCombination losses : neutralLossesCombinations) { + ions.add(new TagFragmentIon(subType, aa, subaa, rewindMass + h2o - losses.getMass(), losses.getNeutralLossCombination(), gap)); + } + + // add the z-ion + subType = TagFragmentIon.Z_ION; + ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(); + ionsMap.put(subType, ions); + } + for (NeutralLossCombination losses : neutralLossesCombinations) { + ions.add(new TagFragmentIon(subType, aa, subaa, rewindMass - nMinusO - losses.getMass(), losses.getNeutralLossCombination(), gap)); + } + } + } + ArrayList newOffsetMasses = new ArrayList<>(); + for (double offsetMass : massOffsets) { + double newMass = offsetMass + sequenceMass; + if (!newOffsetMasses.contains(newMass)) { + newOffsetMasses.add(newMass); + } + } + massOffsets = newOffsetMasses; + ionNumberOffset += aminoAcidSequence.length(); + } else if (tagComponent instanceof MassGap) { + double gapMass = tagComponent.getMass(); + int aa = ionNumberOffset; + int subaa = 0; + + HashMap> ionsMap = result.get(Ion.IonType.TAG_FRAGMENT_ION.index); + if (ionsMap == null) { + ionsMap = new HashMap<>(); + result.put(Ion.IonType.TAG_FRAGMENT_ION.index, ionsMap); + } + for (double massOffset : massOffsets) { + double gap = gapMass; + if (massOffset != Atom.O.getMonoisotopicMass()) { + gap += massOffset; + } + double rewindMass = massOffset + gapMass; + + // add the x-ions + int subType = TagFragmentIon.X_ION; + ArrayList ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(); + ionsMap.put(subType, ions); + } + for (NeutralLossCombination losses : neutralLossesCombinations) { + ions.add(new TagFragmentIon(subType, aa, subaa, rewindMass + co2 - losses.getMass(), losses.getNeutralLossCombination(), gap)); + } + + // add the y-ions + subType = TagFragmentIon.Y_ION; + ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(); + ionsMap.put(subType, ions); + } + for (NeutralLossCombination losses : neutralLossesCombinations) { + ions.add(new TagFragmentIon(subType, aa, subaa, rewindMass + h2o - losses.getMass(), losses.getNeutralLossCombination(), gap)); + } + + // add the z-ion + subType = TagFragmentIon.Z_ION; + ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(); + ionsMap.put(subType, ions); + } + for (NeutralLossCombination losses : neutralLossesCombinations) { + ions.add(new TagFragmentIon(subType, aa, subaa, rewindMass - nMinusO - losses.getMass(), losses.getNeutralLossCombination(), gap)); + } + + } + ArrayList newOffsetMasses = new ArrayList<>(); + for (double offsetMass : massOffsets) { + newOffsetMasses.add(offsetMass + gapMass); + } + massOffsets = newOffsetMasses; + ionNumberOffset++; + } else { + throw new UnsupportedOperationException("Fragment ion not implemented for tag component " + tagComponent.getClass() + "."); + } + } + + // add the precursor ion + HashMap> ionsMap = result.get(Ion.IonType.PRECURSOR_ION.index); + if (ionsMap == null) { + ionsMap = new HashMap<>(1); + result.put(Ion.IonType.PRECURSOR_ION.index, ionsMap); + } + int subType = PrecursorIon.PRECURSOR; + ArrayList ions = ionsMap.get(subType); + if (ions == null) { + ions = new ArrayList<>(neutralLossesCombinations.length); + ionsMap.put(subType, ions); + } + for (NeutralLossCombination losses : neutralLossesCombinations) { + ions.add(new PrecursorIon(tag.getMass() - losses.getMass(), losses.getNeutralLossCombination())); + } + + return result; + } + + /** + * Returns the possible neutral losses combinations as array of arrays of + * neutral losses. + * + * @param possibleNeutralLosses the possible neutral losses to include + * @return the possible neutral losses combinations + */ + public NeutralLossCombination[] getNeutralLossesCombinations(HashSet possibleNeutralLosses) { + + long lossesKey = getNeutralLossesKey(possibleNeutralLosses); + NeutralLossCombination[] neutralLossesCombinations = neutralLossesCombinationsCache.get(lossesKey); + + if (neutralLossesCombinations == null) { + + ArrayList neutralLossesCombinationsLists = estimateNeutralLossesCombinations(possibleNeutralLosses); + neutralLossesCombinations = new NeutralLossCombination[neutralLossesCombinationsLists.size()]; + for (int i = 0; i < neutralLossesCombinationsLists.size(); i++) { + NeutralLoss[] combination = neutralLossesCombinationsLists.get(i); + NeutralLossCombination combinationObject = new NeutralLossCombination(combination); + neutralLossesCombinations[i] = combinationObject; + } + neutralLossesCombinationsCache.put(lossesKey, neutralLossesCombinations); + } + return neutralLossesCombinations; + } + + /** + * Convenience method returning the possible neutral losses combination as + * accounted by the factory, i.e., for now up to two neutral losses per + * peak. + * + * @param possibleNeutralLosses the possible neutral losses + * @return the possible combinations + */ + private ArrayList estimateNeutralLossesCombinations( + HashSet possibleNeutralLosses + ) { + + String[] lossesNames = possibleNeutralLosses.stream().sorted().toArray(String[]::new); + + // We will account for up to two neutral losses per ion maximum + ArrayList neutralLossesCombinations = new ArrayList<>(); + NeutralLoss[] tempList = new NeutralLoss[0]; + neutralLossesCombinations.add(tempList); + + for (int i = 0; i < lossesNames.length; i++) { + + String name1 = lossesNames[i]; + NeutralLoss neutralLoss1 = NeutralLoss.getNeutralLoss(name1); + tempList = new NeutralLoss[1]; + tempList[0] = neutralLoss1; + neutralLossesCombinations.add(tempList); + + for (int j = i + 1; j < lossesNames.length; j++) { + + String name2 = lossesNames[j]; + tempList = new NeutralLoss[2]; + tempList[0] = neutralLoss1; + tempList[1] = NeutralLoss.getNeutralLoss(name2); + neutralLossesCombinations.add(tempList); + + } + } + + return neutralLossesCombinations; + } + + /** + * Returns the neutral losses combination cache key corresponding to a set + * of neutral losses. + * + * @param possibleNeutralLosses the possible neutral losses + * @return the corresponding cache key + */ + private long getNeutralLossesKey( + HashSet possibleNeutralLosses + ) { + return ExperimentObject.asLong(possibleNeutralLosses.stream() + .collect(Collectors.joining())); + } + + /** + * Convenience summing the masses of various neutral losses. + * + * @param neutralLosses list of neutral losses + * @return the sum of the masses + */ + public static double getLossesMass( + NeutralLoss[] neutralLosses + ) { + + return Arrays.stream(neutralLosses) + .mapToDouble(NeutralLoss::getMass) + .sum(); + } +} diff --git a/src/main/java/com/compomics/oglycans/PeptideGenerator.java b/src/main/java/com/compomics/oglycans/PeptideGenerator.java new file mode 100644 index 0000000..5f8a8bf --- /dev/null +++ b/src/main/java/com/compomics/oglycans/PeptideGenerator.java @@ -0,0 +1,143 @@ +package com.compomics.oglycans; + +import com.compomics.util.experiment.biology.enzymes.EnzymeFactory; +import com.compomics.util.experiment.biology.modifications.Modification; +import com.compomics.util.experiment.biology.proteins.Peptide; +import com.compomics.util.experiment.biology.proteins.Protein; +import com.compomics.util.experiment.identification.matches.ModificationMatch; +import com.compomics.util.experiment.identification.protein_sequences.SingleProteinSequenceProvider; +import com.compomics.util.experiment.identification.protein_sequences.digestion.ExtendedPeptide; +import com.compomics.util.experiment.identification.protein_sequences.digestion.ProteinIteratorUtils; +import com.compomics.util.experiment.identification.protein_sequences.digestion.SequenceIterator; +import com.compomics.util.experiment.identification.protein_sequences.digestion.iterators.SpecificSingleEnzymeIterator; +import com.compomics.util.experiment.io.biology.protein.SequenceProvider; +import com.compomics.util.experiment.io.biology.protein.iterators.FastaIterator; +import com.compomics.util.parameters.identification.advanced.SequenceMatchingParameters; +import org.apache.log4j.Logger; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PeptideGenerator { + + private static final Logger LOGGER = Logger.getLogger(PeptideGenerator.class); + + private EnzymeFactory enzymeFactory = EnzymeFactory.getInstance(); + private ProteinIteratorUtils proteinIteratorUtils; + private List variableModifications; + + public PeptideGenerator(List variableModifications) { + proteinIteratorUtils = new ProteinIteratorUtils(Playground.modificationParameters.getFixedModifications(), 1); + this.variableModifications = variableModifications; + } + + /** + * Return a list of all peptide modification combinations from the given peptide FASTA file. + * + * @param fastaFile the FASTA file + * @return a list of {@link Peptide} objects + * @throws FileNotFoundException + */ + public List readPeptideFasta(File fastaFile) throws FileNotFoundException { + List peptides = new ArrayList<>(); + + FastaIterator fastaIterator = new FastaIterator(fastaFile); + Protein protein; + while ((protein = fastaIterator.getNextProtein()) != null) { + List peptideModificationCombinations = getPeptideModificationCombinations(protein, protein.getSequence()); + peptides.addAll(peptideModificationCombinations); + } + + return peptides; + } + + /** + * Returns a map of all peptide modification combinations for each protein from the given protein FASTA file. + * + * @param fastaFile the FASTA file + * @return a list of peptides for each protein + * @throws FileNotFoundException + * @throws InterruptedException + */ + public Map> readProteinFasta(File fastaFile) throws FileNotFoundException, InterruptedException { + Map> proteinPeptides = new HashMap<>(); + + FastaIterator fastaIterator = new FastaIterator(fastaFile); + Protein protein; + while ((protein = fastaIterator.getNextProtein()) != null) { + List extendedPeptides = digestProtein(protein); + List peptides = new ArrayList<>(); + for (ExtendedPeptide extendedPeptide : extendedPeptides) { + List peptideCombinations = getPeptideModificationCombinations(protein, extendedPeptide.peptide.getSequence()); + peptides.addAll(peptideCombinations); + } + proteinPeptides.put(protein, peptides); + } + + return proteinPeptides; + } + + private List digestProtein(Protein protein) throws InterruptedException { + List extendedPeptides = new ArrayList<>(); + + SequenceIterator sequenceIterator = new SpecificSingleEnzymeIterator(proteinIteratorUtils, protein.getSequence(), enzymeFactory.getEnzyme("Trypsin"), 0, 800.0, 10000.0); + ExtendedPeptide extendedPeptide; + while ((extendedPeptide = sequenceIterator.getNextPeptide()) != null) { + extendedPeptides.add(extendedPeptide); + } + + return extendedPeptides; + } + + private List getPeptideModificationCombinations(Protein protein, String peptideSequence) { + List peptides = new ArrayList<>(); + + // I'm not sure if this is important + SequenceProvider sequenceProvider = new SingleProteinSequenceProvider(protein); + + LOGGER.info("Calculating modification combinations for " + peptideSequence); + + List> singleModificationCombinations = new ArrayList<>(); + List uniqueModificationCombinations = new ArrayList<>(); + for (Modification variableModification : variableModifications) { + List modificationSiteCombinations = CombinationUtils.getModificationSiteCombinations(variableModification, protein, peptideSequence); + singleModificationCombinations.add(modificationSiteCombinations); + modificationSiteCombinations.forEach(combination -> CombinationUtils.addArrayToList(uniqueModificationCombinations, combination)); + } + + // for each variable modification, combine the possible modifications with the other modification combinations + // and only keep the unique combinations + for (int i = 0; i < variableModifications.size(); i++) { + List newCombinations = CombinationUtils.combineModificationCombinations(uniqueModificationCombinations); + newCombinations.forEach(newCombination -> CombinationUtils.addArrayToList(uniqueModificationCombinations, newCombination)); + } + for (String[] uniqueModificationCombination : uniqueModificationCombinations) { + Peptide peptide = new Peptide(peptideSequence); + for (int i = 0; i < peptide.getSequence().length(); i++) { + if (uniqueModificationCombination[i] != null) { + // check for pyroGlu + // TODO right now pyroGlu is on index 0 of the peptide because it's an N-terminal modification, check if this is OK + //if(ModificationFactory.getInstance().getModification(uniqueModificationCombination[i]).getModificationType() == ModificationType.modnaa_peptide){ + if (uniqueModificationCombination[i].equals(Playground.pyroGly.getName())) { + peptide.addVariableModification(new ModificationMatch(uniqueModificationCombination[i], i)); + } else { + peptide.addVariableModification(new ModificationMatch(uniqueModificationCombination[i], i + 1)); + } + } + } + peptide.estimateTheoreticMass(Playground.modificationParameters, sequenceProvider, SequenceMatchingParameters.getDefaultSequenceMatching()); + //System.out.print(peptide.getSequence() + " " + peptide.getMass() + " -> "); + //System.out.println(Arrays.toString(peptide.getIndexedVariableModifications())); + peptides.add(peptide); + } + + LOGGER.info("Found " + peptides.size() + " modification combinations for " + peptideSequence); + + return peptides; + } + +} diff --git a/src/main/java/com/compomics/oglycans/PeptideIons.java b/src/main/java/com/compomics/oglycans/PeptideIons.java new file mode 100644 index 0000000..9a0a580 --- /dev/null +++ b/src/main/java/com/compomics/oglycans/PeptideIons.java @@ -0,0 +1,241 @@ +package com.compomics.oglycans; + +import com.compomics.ms2io.model.Modification; +import com.compomics.util.AA_Mass; +import com.compomics.util.AtomMass; +import com.compomics.util.experiment.biology.ions.Ion; +import com.compomics.util.experiment.biology.ions.impl.PeptideFragmentIon; +import com.compomics.util.experiment.biology.proteins.Peptide; +import com.compomics.util.experiment.biology.proteins.Protein; +import com.compomics.util.experiment.identification.protein_sequences.SingleProteinSequenceProvider; +import com.compomics.util.experiment.io.biology.protein.SequenceProvider; +import com.compomics.util.parameters.identification.advanced.SequenceMatchingParameters; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author Genet + */ +public class PeptideIons { + + private String sequence = ""; + private ArrayList ions; + private Map fragmentIons; + private Map modifications; + private HashMap>> utlitiesFragmentIons; + + /** + * Constructor that takes a utilities {@link Peptide} object. + * + * @param peptide the peptide object + */ + public PeptideIons(Peptide peptide, boolean decoy) { + modifications = new HashMap<>(); + ions = new ArrayList<>(); + this.sequence = peptide.getSequence(); + SequenceProvider sequenceProvider = new SingleProteinSequenceProvider(new Protein("DUMMY_ACCESSION", peptide.getSequence())); + String[] variableModifications = peptide.getIndexedVariableModifications(); + String[] fixedModifications = peptide.getFixedModifications(Playground.modificationParameters, sequenceProvider, SequenceMatchingParameters.getDefaultSequenceMatching()); + int index; + this.utlitiesFragmentIons = IonFactory.getInstance().getFragmentIons(peptide, Playground.modificationParameters, sequenceProvider, SequenceMatchingParameters.getDefaultSequenceMatching()); + //printUtilitiesFragmentIons(); + for (int i = 0; i < variableModifications.length; i++) { + if (variableModifications[i] != null) { + com.compomics.util.experiment.biology.modifications.Modification utilitiesModification = Playground.utilitiesModifications.get(variableModifications[i]); + + if (variableModifications[i].equals(Playground.pyroGly.getName())) { + index = i; + } else { + index = i - 1; + } + + if (decoy) { + if (index != this.sequence.length() - 1) { + index = this.sequence.length() - 2 - index; + } + } + + Modification modification = new Modification(index, peptide.getSequence().charAt(index), utilitiesModification.getMass(), utilitiesModification.getName()); + modifications.put(index, modification); + } + } + + for (int i = 0; i < fixedModifications.length; i++) { + + if (fixedModifications[i] != null) { + com.compomics.util.experiment.biology.modifications.Modification utilitiesModification = Playground.utilitiesModifications.get(fixedModifications[i]); + index = i - 1; + Modification modification = new Modification(index, peptide.getSequence().charAt(index), utilitiesModification.getMass(), utilitiesModification.getName()); + modifications.put(index, modification); + } + } + //fragment(); + } + + /** + * Generate the (fragment, precursor) ions for the given peptide. + * + * @param fragmentIonCharges the fragment ion charges to consider + * @return the list of ions + */ + public List generateIons(List fragmentIonCharges) { + HashMap> peptideFragmentIons = utlitiesFragmentIons.get(Ion.IonType.PEPTIDE_FRAGMENT_ION.index); + for (Integer charge : fragmentIonCharges) { + // y ions + ArrayList ions = peptideFragmentIons.get(PeptideFragmentIon.Y_ION); + this.ions.addAll(ions.stream().filter(ion -> ion.getName().equals("y")).map(ion -> ion.getTheoreticMz(charge)).collect(Collectors.toList())); + // b ions + ions = peptideFragmentIons.get(PeptideFragmentIon.B_ION); + this.ions.addAll(ions.stream().filter(ion -> ion.getName().equals("b")).map(ion -> ion.getTheoreticMz(charge)).collect(Collectors.toList())); + // z ions + ions = peptideFragmentIons.get(PeptideFragmentIon.Z_ION); + this.ions.addAll(ions.stream().filter(ion -> ion.getName().equals("z")).map(ion -> ion.getTheoreticMz(charge)).collect(Collectors.toList())); + // c ions + ions = peptideFragmentIons.get(PeptideFragmentIon.C_ION); + this.ions.addAll(ions.stream().filter(ion -> ion.getName().equals("c")).map(ion -> ion.getTheoreticMz(charge)).collect(Collectors.toList())); + + HashMap> precursorIons = utlitiesFragmentIons.get(Ion.IonType.PRECURSOR_ION.index); + this.ions.addAll(precursorIons.get(0).stream().map(ion -> ion.getTheoreticMz(charge)).collect(Collectors.toList())); + } + + Collections.sort(ions); + return ions; + } + + private void fragment() { + this.sequence = this.sequence.replaceAll("\\s+", ""); + int len_seq = sequence.length(); + int last_index = len_seq - 1; + for (int i = 0; i < len_seq; i++) { + String b_ion = sequence.substring(0, i + 1); + String y_ion = sequence.substring(last_index - i, len_seq); + + int len_chars = i + 1; + double b_mass = 0; + double a_mass; + double c_mass; + double y_mass = 0; + double z_mass; + int bion_oglycans = 0; + int yion_oglycans = 0; + + for (int j = 0; j < len_chars; j++) { + + //String suffix = Integer.toString(len_chars); //number to append to the ion type + + int y_index_track = last_index - i; + Modification mods; + b_mass += AA_Mass.getAA_mass(b_ion.charAt(j)); + y_mass += AA_Mass.getAA_mass(y_ion.charAt(j)); + + if (!modifications.isEmpty()) { + if (modifications.containsKey(j)) { + //iterate over list of modification at this AA position + + mods = modifications.get(j); + double mod = mods.getModificationMassShift(); + +// for (int k = 0; k < mods.size(); k++) { +// mod += Modification_Mass.getMassShift(mods.get(k)); +// +// } + b_mass += mod; + if (Math.abs(mod - 503.3) < 0.001) { + bion_oglycans++; + } + } + if (modifications.containsKey(y_index_track + j)) { + //iterate over list of modification at this AA position + mods = modifications.get(y_index_track + j); + double mod = mods.getModificationMassShift(); +// for (int k = 0; k < mods.size(); k++) { +// mod += Modification_Mass.getMassShift(mods.get(k)); +// } + y_mass += mod; + + if (Math.abs(mod - 503.3) < 0.001) { + yion_oglycans++; + } + } + + } + + } + + y_mass += AtomMass.getAtomMass("H1") * 2 + AtomMass.getAtomMass("O16");//water loss?? + a_mass = b_mass - (AtomMass.getAtomMass("C12") + AtomMass.getAtomMass("O16")); + //fragments added for glycan fragments + c_mass = b_mass + (AtomMass.getAtomMass("N15") + AtomMass.getAtomMass("H1")); + z_mass = y_mass - (AtomMass.getAtomMass("N15") + AtomMass.getAtomMass("H1")); + + //remove the oglycan mass shift from b and y ions, if it is already added(yion_oglycan!=0) + y_mass = y_mass - yion_oglycans * 503.3; + b_mass = b_mass - bion_oglycans * 503.3; + + + ions.add(y_mass); +// frag_ion.add(y_mass / 2); +// +// frag_ion.add(b_mass); +// frag_ion.add(b_mass / 2); +// frag_ion.add(a_mass); +// frag_ion.add(a_mass / 2); +// frag_ion.add(c_mass); +// frag_ion.add(c_mass / 2); +// frag_ion.add(z_mass); +// frag_ion.add(z_mass + 1); +// frag_ion.add(z_mass + 1); +// frag_ion.add(z_mass / 2); +// frag_ion.add(z_mass / 3); +// frag_ion.add(z_mass / 4); + + +// frag_ion.add(Math.roung(y_mass*10000)/10000.0d); +// frag_ion.add(Math.roung(y_mass*10000)/20000.0d); +// +// frag_ion.add(Math.roung(b_mass*10000)/10000.0d); +// frag_ion.add(Math.roung(b_mass*10000)/20000.0d); +// frag_ion.add(Math.roung(a_mass*10000)/10000.0d); +// frag_ion.add(Math.roung(a_mass*10000)/20000.0d); +// frag_ion.add(Math.roung(c_mass*10000)/10000.0d); +// frag_ion.add(Math.roung(c_mass*10000)/20000.0d); +// frag_ion.add(Math.roung(z_mass*10000)/10000.0d); +// frag_ion.add(Math.roung(z_mass*10000)/20000.0d); +// frag_ion.add(Math.roung(z_mass*10000)/30000.0d); +// frag_ion.add(Math.roung(z_mass*10000)/40000.0d); + } + ions = (ArrayList) ions.stream().distinct().collect(Collectors.toList()); + } + + private void printUtilitiesFragmentIons() { + HashMap> peptideFragments = utlitiesFragmentIons.get(Ion.IonType.PEPTIDE_FRAGMENT_ION.index); + ArrayList ions = peptideFragments.get(PeptideFragmentIon.Y_ION); + HashMap> precursor = utlitiesFragmentIons.get(Ion.IonType.PRECURSOR_ION.index); + System.out.println(""); + for (int i = 0; i < ions.size(); i++) { + if (ions.get(i).getName().equals("y")) { + System.out.println(ions.get(i).getName() + " " + ions.get(i).getTheoreticMass() + " " + ions.get(i).getTheoreticMz(1)); + } + } + + } + + /** + * return fragment ion , mass map of sequence + * + * @return + */ + public ArrayList getFragmentIon() { + return ions; + } + + /** + * return modification + * + * @return + */ + public Map getModification() { + return this.modifications; + } +} diff --git a/src/main/java/com/compomics/oglycans/Playground.java b/src/main/java/com/compomics/oglycans/Playground.java new file mode 100644 index 0000000..5d9e04b --- /dev/null +++ b/src/main/java/com/compomics/oglycans/Playground.java @@ -0,0 +1,98 @@ +package com.compomics.oglycans; + +import com.compomics.coss.model.ResourceUtils; +import com.compomics.util.AtomMass; +import com.compomics.util.experiment.biology.modifications.Modification; +import com.compomics.util.experiment.biology.modifications.ModificationCategory; +import com.compomics.util.experiment.biology.modifications.ModificationFactory; +import com.compomics.util.experiment.biology.modifications.ModificationType; +import com.compomics.util.experiment.biology.proteins.Peptide; +import com.compomics.util.experiment.io.mass_spectrometry.mgf.MgfFileIterator; +import com.compomics.util.experiment.mass_spectrometry.spectra.Spectrum; +import com.compomics.util.gui.waiting.waitinghandlers.WaitingHandlerDummy; +import com.compomics.util.parameters.identification.search.ModificationParameters; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Playground { + + private static ModificationFactory modificationFactory = ModificationFactory.getInstance(); + public static final ModificationParameters modificationParameters = new ModificationParameters(); + public static Modification oglycan; + public static final Modification oxidation = modificationFactory.getModification("Oxidation of M"); + public static final Modification pyroGly = modificationFactory.getModification("Pyrolidone from E"); + public static final Modification carbo = modificationFactory.getModification("Carbamidomethylation of C"); + public static Map utilitiesModifications = new HashMap<>(); + private static List variableModifications = new ArrayList<>(); + + static { + // add O-glycans mod with TMT label to ModificationFactory + ArrayList residues = new ArrayList<>(); + residues.add("S"); + residues.add("T"); + oglycan = new Modification(ModificationType.modaa, "oglycans", 503.3, residues, ModificationCategory.Common); + modificationFactory.addUserModification(oglycan); + + modificationParameters.addFixedModification(carbo); + modificationParameters.addVariableModification(oglycan); + modificationParameters.addVariableModification(oxidation); + modificationParameters.addVariableModification(pyroGly); + + utilitiesModifications.put("oglycans", oglycan); + utilitiesModifications.put("Oxidation of M", oxidation); + utilitiesModifications.put("Pyrolidone from E", pyroGly); + utilitiesModifications.put("Carbamidomethylation of C", carbo); + + variableModifications.add(oglycan); + variableModifications.add(oxidation); + variableModifications.add(pyroGly); + } + + public Playground() { + } + + public static void main(String[] args) { + List precursorCharges = new ArrayList<>(); + precursorCharges.add(2); + precursorCharges.add(4); + precursorCharges.add(5); + + try { + File output_file = new File("test.msp"); + if (output_file.exists()) { + output_file.delete(); + } + + PeptideGenerator peptideGenerator = new PeptideGenerator(variableModifications); + List peptides = peptideGenerator.readPeptideFasta(ResourceUtils.getResourceByRelativePath("GlycopeptidePoolSmall.fasta").getFile()); + + // read the MGF file +// MgfFileIterator mgfFileIterator = new MgfFileIterator(new File("/home/niels/Downloads/Niels_glycopeptide_pool/CMB-763_EThcD_export.mgf"), new WaitingHandlerDummy()); +// while (mgfFileIterator.next() != null) { +// Spectrum spectrum = mgfFileIterator.getSpectrum(); +// for (Peptide peptide : peptides) { +// for (Integer precursorCharge : precursorCharges) { +// if (Math.abs((peptide.getMass() / precursorCharge) + precursorCharge * AtomMass.getAtomMass("H1") - spectrum.precursor.getMass(precursorCharge)) < 0.5) { +// System.out.println("match"); +// } +// } +// } +// } + + SpectrumGenerator spectrumGenerator = new SpectrumGenerator(); + spectrumGenerator.generateSpectra(peptides, output_file); + + System.out.println(""); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/compomics/oglycans/SpectrumGenerator.java b/src/main/java/com/compomics/oglycans/SpectrumGenerator.java new file mode 100644 index 0000000..02ba5c1 --- /dev/null +++ b/src/main/java/com/compomics/oglycans/SpectrumGenerator.java @@ -0,0 +1,136 @@ +package com.compomics.oglycans; + +import com.compomics.ms2io.model.*; +import com.compomics.ms2io.controller.*; +import com.compomics.util.AtomMass; +import com.compomics.util.experiment.biology.proteins.Peptide; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Map; +import java.util.List; + +import org.apache.commons.lang3.ArrayUtils; + +/** + * @author Genet + */ +public class SpectrumGenerator { + + private List precursorCharges; + private List fragmentIonCharges; + + public SpectrumGenerator() { + precursorCharges = new ArrayList<>(); + precursorCharges.add(2); + precursorCharges.add(3); + precursorCharges.add(4); + + fragmentIonCharges = new ArrayList<>(); + fragmentIonCharges.add(1); +// fragmentIonCharges.add(2); + } + + public void generateSpectra(List peptides, File mgf_file) throws IOException { + SpectraWriter spw = new MspWriter(mgf_file); + + ArrayList peaks = new ArrayList<>(); + ArrayList decoyPeaks = new ArrayList<>(); + for (Peptide peptide : peptides) { + + // get fragment ions of the peptide + PeptideIons peptideIons = new PeptideIons(peptide, false); + List ions = peptideIons.generateIons(fragmentIonCharges); + + // peak list + for (Double d : ions) { + Peak peak = new Peak(d, 600, ""); + peaks.add(peak); + } + + String mod_str = ""; + for (Map.Entry entry : peptideIons.getModification().entrySet()) { + mod_str += entry.getValue().getModificationPosition() + "," + entry.getValue().getModifiedAA() + "," + entry.getValue().getModificationMassShift() + "\\"; + } + if (mod_str != "") { + mod_str = mod_str.substring(0, mod_str.length() - 1); + } else { + mod_str = "0"; + } + + // make a spectrum for each precursor charge + for (Integer precursorCharge : precursorCharges) { + Spectrum spectrum = new Spectrum(); + spectrum.setComment("Comment: " + "Parent=" + ((peptide.getMass() + precursorCharge * AtomMass.getAtomMass("H1")) / precursorCharge) + " " + "Mods=" + mod_str); + spectrum.setMW(0); + spectrum.setSequence(peptide.getSequence()); + spectrum.setPCMass(peptide.getMass()); + spectrum.setTitle(peptide.getSequence() + "/" + precursorCharge); + spectrum.setNumPeaks(ions.size()); + spectrum.setPeakList(peaks); + spectrum.setCharge(precursorCharge.toString()); + spw.write(spectrum); + } + + + // Generate decoy fragment ions from reverse sequence + // reverse sequence except the last aa + char[] tempSequence = peptide.getSequence().substring(0, peptide.getSequence().length() - 1).toCharArray(); + ArrayUtils.reverse(tempSequence); + String reverseSequence = new String(tempSequence); + //add last aa to reversed sequence + reverseSequence += peptide.getSequence().charAt(peptide.getSequence().length() - 1); + + //decoy_pep=peptide; + peptide.setSequence(reverseSequence); + //decoy_pep = new Peptide(rev_sequence); + // TODO ask Genet how to do this + PeptideIons decoyPeptideIons = new PeptideIons(peptide, true); + + List decoyIons = decoyPeptideIons.generateIons(fragmentIonCharges); + Collections.sort(decoyIons); + + //peak list of decoy + for (Double dd : decoyIons) { + Peak decoyPeak = new Peak(dd, 600, ""); + decoyPeaks.add(decoyPeak); + } + + + Spectrum decoySpectrum = new Spectrum(); + mod_str = ""; + for (Map.Entry entry : decoyPeptideIons.getModification().entrySet()) { + mod_str += entry.getValue().getModificationPosition() + "," + entry.getValue().getModifiedAA() + "," + entry.getValue().getModificationMassShift() + "\\"; + + } + if (mod_str != "") { + mod_str = mod_str.substring(0, mod_str.length() - 1); + } else { + mod_str = "0"; + } + + for (Integer precursorCharge : precursorCharges) { + decoySpectrum.setComment("Comment: " + "Parent=" + ((peptide.getMass() + precursorCharge * AtomMass.getAtomMass("H1")) / precursorCharge) + " " + "Mods=" + mod_str + " _decoy"); + decoySpectrum.setMW(0); + decoySpectrum.setSequence(reverseSequence); + decoySpectrum.setPCMass(peptide.getMass()); + decoySpectrum.setTitle(reverseSequence + "/" + precursorCharge); + decoySpectrum.setNumPeaks(decoyIons.size()); + decoySpectrum.setPeakList(decoyPeaks); + decoySpectrum.setCharge(precursorCharge.toString()); + spw.write(decoySpectrum); + } + + peaks.clear(); + decoyPeaks.clear(); + ions.clear(); + decoyIons.clear(); + + } + spw.closeWriter(); + + } + +} diff --git a/src/main/java/com/compomics/util/FragmentIon.java b/src/main/java/com/compomics/util/FragmentIon.java index 63731f2..5f94857 100644 --- a/src/main/java/com/compomics/util/FragmentIon.java +++ b/src/main/java/com/compomics/util/FragmentIon.java @@ -48,7 +48,6 @@ private void fragment() { int y_index_track =last_index - i; Modification mods; for (int j = 0; j < len_chars; j++) { - b_mass += AA_Mass.getAA_mass(b_ion.charAt(j)); y_mass += AA_Mass.getAA_mass(y_ion.charAt(j)); diff --git a/src/main/java/com/compomics/util/Modification_Mass.java b/src/main/java/com/compomics/util/Modification_Mass.java index f7c2ed3..375fbc9 100644 --- a/src/main/java/com/compomics/util/Modification_Mass.java +++ b/src/main/java/com/compomics/util/Modification_Mass.java @@ -11,6 +11,7 @@ */ public final class Modification_Mass { + private static final double OGlycan = 503.3; private static final double CAM = 57.021464; private static final double Oxidation = 15.994915; private static final double Pyro_glu_E = -18.010565; // Pyro-glu from E (Glu -> pyro-Glu) //modified @@ -59,6 +60,9 @@ public static double getMassShift(String mod_name){ double mass=0.0; switch(mod_name){ + + case "OGlycan": mass = 503.3; + break; case "CAM": mass = 57.021464; break; case "Oxidation": mass = 15.994915; diff --git a/src/main/resources/GlycopeptidePool.fasta b/src/main/resources/GlycopeptidePool.fasta new file mode 100644 index 0000000..f333d81 --- /dev/null +++ b/src/main/resources/GlycopeptidePool.fasta @@ -0,0 +1,299 @@ +>1 +AMSEVTSLHEDDWR + +>2 +APIISGVTK + +>3 +APVGSVVSVPSQSSASSDK + +>4 +AQPSASLGVGYR + +>5 +ASPPLFQSR + +>6 +ASTPGAAAQIQEVK + +>7 +ATAVVDGAFK + +>8 +AVAITQSPSSVR + +>9 +DSLGVSFPEELACK + +>10 +DVFISAAER + +>11 +EEKPAVTAAPK + +>12 +EGFSIPVSADGFK + +>13 +ELANFDPSRPGPPSGR + +>14 +ESISVSSEQLAQFR + +>15 +EVVKPVPITSPAVSK + +>16 +FELLPTPPLSPSRR + +>17 +FGVEAFSDCLR + +>18 +FIHQQPQSSSPVYGSSAK + +>19 +FSPPSSSLQPGK + +>20 +FSYTSQHSDYGQR + +>21 +FSYTSQHSDYGQR + +>22 +GSHGQTPSPGALPLGR + +>23 +HVSPVTPPR + +>24 +IEDEQALGSQLQK + +>25 +IGSLDNITHVPGGGNK + +>26 +IPAASAAAMNLASAR + +>27 +IQTVPASHLQQGTASGSSK + +>28 +ISEILLDHGAPIQAK + +>29 +ISEILLDHGAPIQAK + +>30 +KSQAGASELGPFSDPR + +>31 +KVTLSVLSR + +>32 +LGHYATQLQK + +>33 +LGSASSSHGSIQESHK + +>34 +LSEHATAPTR + +>35 +LSESHPDATEDLQR + +>36 +LSQEDPDYGIR + +>37 +LSTPPPLAEEEGLASR + +>38 +LVSESSDVLPK + +>39 +MFLSFPTTK + +>40 +MSQQYGDVLQIR + +>41 +MTLSVLSR + +>42 +NLVTGDHIPTPQDLPQR + +>43 +QGNAVTLGDYYQGR + +>44 +RFSPPSSSLQPGK + +>45 +SGYSSPGSPGTPGSR + +>46 +SISQSISGQK + +>47 +SLYASSPGGVYATR + +>48 +SSDLTDRVK + +>49 +SSSAGGQGSYVPLLR + +>50 +SVGGSGGGSFGDNLVTR + +>51 +SYISSQTNDTHK + +>52 +TLTPASSPVSSPSKHGDR + +>53 +TQSFSLQER + +>54 +TSAVSSQANSQPPVQVSVK + +>55 +TSSEASVSSSVAK + +>56 +TTSYPTPRPYPKPAPSSGK + +>57 +VAVLGASGGIGQPLSLLLK + +>58 +VILENIASHEPR + +>59 +VLDASWYSPGTR + +>60 +VLPSITTEILK + +>61 +VLSIGDGIAR + +>62 +VMVAPISGSVTTGTK + +>63 +VPQAQPTKPALK + +>64 +VTGGIFSVTK + +>65 +YIDNQVVSTKGER + +>66 +TTLTSDESVKDHTTAGR + +>67 +LSFGLEDEPLETATK + +>68 +GQDSTIAASEQQVAAR + +>69 +LVTLEEFLASTQR + +>70 +DYSQPTAAATVQDIK + +>71 +DFSLTSSSQTPGATK + +>72 +ASTYGSTQQLAEMWLEK + +>73 +ITATTTQVTSTTTQDTTPFK + +>74 +TEITSTAETFGFEAK + +>75 +VEELEGEITTLNHK + +>76 +KITESVAETAQTIK + +>77 +LGNTISSLFGGGTTPDAK + +>78 +TAGSSGVTAGRPRPTAR + +>79 +VGADGTVFATR + +>80 +TATLATLATR + +>81 +ITESVAETAQTIK + +>82 +ITESVAETAQTIKK + +>83 +RLDINTNTYTSQDLK + +>84 +ETTPSSLAVTQTMATK + +>85 +SALAAAQTQVAEYK + +>86 +STLEEPNLQPLQR + +>87 +THLGEALAPLSK + +>88 +SLIGKVDGTSHVTGK + +>89 +SFSASGAQIVSR + +>90 +TELLPGDRDNLAIQTR + +>91 +LPTTAASTPDAVDK + +>92 +DHSKPISNPSDNK + +>93 +TPLTHALPGLSEQEGQK + +>94 +SAGSVESPSVSSTHR + +>95 +ISPVEESEDVSNK + +>96 +EPFSGDHSADGFEVTSR + +>97 +QQETAAAETETR + +>98 +SQLANTEPTK + +>99 +HEVTGWVLVSPLSK + +>100 +VDGDTQTTVEK \ No newline at end of file diff --git a/src/main/resources/GlycopeptidePoolSmall.fasta b/src/main/resources/GlycopeptidePoolSmall.fasta new file mode 100644 index 0000000..ad764ea --- /dev/null +++ b/src/main/resources/GlycopeptidePoolSmall.fasta @@ -0,0 +1,2 @@ +>1 +AMSEVTSLHEDDWR diff --git a/src/main/resources/PeptidePoolContatenated.fasta b/src/main/resources/PeptidePoolContatenated.fasta new file mode 100644 index 0000000..8a94510 --- /dev/null +++ b/src/main/resources/PeptidePoolContatenated.fasta @@ -0,0 +1,2 @@ +>tr|W00001|W00001_HUMAN Concatenated Peptide Pool OS=Homo sapiens OX=9606 GN=IFNGR2 PE=1 SV=1 +AMSEVTSLHEDDWRAPIISGVTKAPVGSVVSVPSQSSASSDKAQPSASLGVGYRASPPLFQSRASTPGAAAQIQEVKATAVVDGAFKAVAITQSPSSVRDSLGVSFPEELACKDVFISAAEREEKPAVTAAPKEGFSIPVSADGFKELANFDPSRPGPPSGRESISVSSEQLAQFREVVKPVPITSPAVSKFELLPTPPLSPSRRFGVEAFSDCLRFIHQQPQSSSPVYGSSAKFSPPSSSLQPGKFSYTSQHSDYGQRGSAPPGPVPEGSIRGSHGQTPSPGALPLGRHVSPVTPPRIEDEQALGSQLQKIGSLDNITHVPGGGNKIPAASAAAMNLASARIQTVPASHLQQGTASGSSKISEILLDHGAPIQAKIVNVSLADLRKSQAGASELGPFSDPRKVTLSVLSRLGHYATQLQKLGSASSSHGSIQESHKLSEHATAPTRLSESHPDATEDLQRLSQEDPDYGIRLSTPPPLAEEEGLASRLVSESSDVLPKMFLSFPTTKMSQQYGDVLQIRMTLSVLSRNLVTGDHIPTPQDLPQRQGNAVTLGDYYQGRRFSPPSSSLQPGKSGYSSPGSPGTPGSRSISQSISGQKSLYASSPGGVYATRSSDLTDRVKSSSAGGQGSYVPLLRSVGGSGGGSFGDNLVTRSYISSQTNDTHKTLTPASSPVSSPSKHGDRTQSFSLQERTSAVSSQANSQPPVQVSVKTSSEASVSSSVAKTTSYPTPRPYPKPAPSSGKVAVLGASGGIGQPLSLLLKVILENIASHEPRVLDASWYSPGTRVLPSITTEILKVLSIGDGIARVMVAPISGSVTTGTKVPQAQPTKPALKVTGGIFSVTKYIDNQVVSTKGERTTLTSDESVKDHTTAGRLSFGLEDEPLETATKGQDSTIAASEQQVAARLVTLEEFLASTQRDYSQPTAAATVQDIKDFSLTSSSQTPGATKASTYGSTQQLAEMWLEKITATTTQVTSTTTQDTTPFKTEITSTAETFGFEAKVEELEGEITTLNHKKITESVAETAQTIKLGNTISSLFGGGTTPDAKTAGSSGVTAGRPRPTARVGADGTVFATRTATLATLATRITESVAETAQTIKITESVAETAQTIKKRLDINTNTYTSQDLKETTPSSLAVTQTMATKSALAAAQTQVAEYKSTLEEPNLQPLQRTHLGEALAPLSKSLIGKVDGTSHVTGKSFSASGAQIVSRTELLPGDRDNLAIQTRLPTTAASTPDAVDKDHSKPISNPSDNKTPLTHALPGLSEQEGQKSAGSVESPSVSSTHRISPVEESEDVSNKEPFSGDHSADGFEVTSRQQETAAAETETRSQLANTEPTKHEVTGWVLVSPLSKVDGDTQTTVEK diff --git a/src/main/resources/config.properties b/src/main/resources/config.properties index dfce80c..090ac33 100644 --- a/src/main/resources/config.properties +++ b/src/main/resources/config.properties @@ -5,9 +5,9 @@ coss.version = 1.0 ############################## -target.spectra.path =D:/percolator_coss_test/Adult_Colon_bRP_Elite_50_f24.mgf +target.spectra.path =/home/niels/Downloads/Niels_glycopeptide_pool/Unfiltered_EThcD_111.mgf #C:/Users/Genet/OneDrive - UGent/6_TestFilesNAnalysis/SpecA.msp -spectra.library.path = D:/human_hcd_fromC/lib/PRIDE/Human_TDrandomIntMzShift.msp +spectra.library.path = /home/niels/Documents/Development/Projects/COSS/test.msp # C:/Users/Genet/OneDrive - UGent/6_TestFilesNAnalysis/SpecB.msp #C:/Users/Genet/OneDrive - UGent/6_TestFilesNAnalysis/SpecA.msb #C:/Users/Genet/OneDrive - UGent/6_TestFilesNAnalysis/SpecB.msb @@ -17,9 +17,9 @@ result.path = D:/COSS_Result ## MS1 and MS2error value in ppm ## If this is set to 0, no precursor tolerance is selected (in Da) -precursor.tolerance = 10 +precursor.tolerance = 0.5 # The fragment tolerance unit is in ppm. -fragment.tolerance = 0.05 +fragment.tolerance = 10 ############################## ## Preprocessing parameters ## diff --git a/src/test/java/com/compomics/coss/oglycans/CombinationUtilsTest.java b/src/test/java/com/compomics/coss/oglycans/CombinationUtilsTest.java new file mode 100644 index 0000000..aa30069 --- /dev/null +++ b/src/test/java/com/compomics/coss/oglycans/CombinationUtilsTest.java @@ -0,0 +1,87 @@ +package com.compomics.coss.oglycans; + +import com.compomics.oglycans.CombinationUtils; +import com.compomics.util.experiment.biology.modifications.Modification; +import com.compomics.util.experiment.biology.modifications.ModificationCategory; +import com.compomics.util.experiment.biology.modifications.ModificationFactory; +import com.compomics.util.experiment.biology.modifications.ModificationType; +import com.compomics.util.experiment.biology.proteins.Protein; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CombinationUtilsTest { + + private static ModificationFactory modificationFactory = ModificationFactory.getInstance(); + + @BeforeClass + public static void setUpClass() throws Exception { + // add O-glycans mod with TMT label to ModificationFactory + ArrayList residues = new ArrayList<>(); + residues.add("S"); + residues.add("T"); + Modification oglycan = new Modification(ModificationType.modaa, "oglycans", 503.3, residues, ModificationCategory.Common); + modificationFactory.addUserModification(oglycan); + } + + @Test + public void testCombineModificationCombinations() { + List modificationCombinations = new ArrayList<>(); + modificationCombinations.add(new String[]{"mod1", null, null}); + modificationCombinations.add(new String[]{null, "mod2", null}); + modificationCombinations.add(new String[]{null, null, "mod3"}); + + List combinations = CombinationUtils.combineModificationCombinations(modificationCombinations); + Assert.assertEquals(3, combinations.size()); + Assert.assertTrue(combinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{"mod1", "mod2", null}))); + Assert.assertTrue(combinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{"mod1", null, "mod3"}))); + Assert.assertTrue(combinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{null, "mod2", "mod3"}))); + } + + @Test + public void testGetCombinationsForModificationOccurrence() { + List possibleModificationSiteCombinations = CombinationUtils.getCombinationsForModificationOccurrence(8, "mod", new int[]{2, 4, 6}, 0); + Assert.assertEquals(1, possibleModificationSiteCombinations.size()); + Assert.assertTrue(possibleModificationSiteCombinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{null, null, null, null, null, null, null, null}))); + + possibleModificationSiteCombinations = CombinationUtils.getCombinationsForModificationOccurrence(8, "mod", new int[]{2, 4, 6}, 1); + + Assert.assertEquals(3, possibleModificationSiteCombinations.size()); + Assert.assertTrue(possibleModificationSiteCombinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{null, "mod", null, null, null, null, null, null}))); + Assert.assertTrue(possibleModificationSiteCombinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{null, null, null, null, null, "mod", null, null}))); + Assert.assertTrue(possibleModificationSiteCombinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{null, null, null, "mod", null, null, null, null}))); + + possibleModificationSiteCombinations = CombinationUtils.getCombinationsForModificationOccurrence(8, "mod", new int[]{2, 4, 6}, 2); + + Assert.assertEquals(3, possibleModificationSiteCombinations.size()); + Assert.assertTrue(possibleModificationSiteCombinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{null, "mod", null, "mod", null, null, null, null}))); + Assert.assertTrue(possibleModificationSiteCombinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{null, "mod", null, null, null, "mod", null, null}))); + Assert.assertTrue(possibleModificationSiteCombinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{null, null, null, "mod", null, "mod", null, null}))); + + possibleModificationSiteCombinations = CombinationUtils.getCombinationsForModificationOccurrence(8, "mod", new int[]{2, 4, 6}, 3); + + Assert.assertEquals(1, possibleModificationSiteCombinations.size()); + Assert.assertTrue(possibleModificationSiteCombinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{null, "mod", null, "mod", null, "mod", null, null}))); + } + + @Test + public void testGetModificationSiteCombinations() { + Protein protein = new Protein("TEST", "TEST"); + List combinations = CombinationUtils.getModificationSiteCombinations(modificationFactory.getModification("oglycans"), protein, "TEST"); + Assert.assertEquals(8, combinations.size()); + Assert.assertTrue(combinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{null, null, null, null}))); + Assert.assertTrue(combinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{"oglycans", null, null, null}))); + Assert.assertTrue(combinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{null, null, "oglycans", null}))); + Assert.assertTrue(combinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{null, null, null, "oglycans"}))); + Assert.assertTrue(combinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{"oglycans", null, "oglycans", null}))); + Assert.assertTrue(combinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{"oglycans", null, null, "oglycans"}))); + Assert.assertTrue(combinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{null, null, "oglycans", "oglycans"}))); + Assert.assertTrue(combinations.stream().anyMatch(a -> Arrays.equals(a, new String[]{"oglycans", null, "oglycans", "oglycans"}))); + } + +} diff --git a/src/test/java/com/compomics/coss/oglycans/PeptideGeneratorTest.java b/src/test/java/com/compomics/coss/oglycans/PeptideGeneratorTest.java new file mode 100644 index 0000000..a14b4f1 --- /dev/null +++ b/src/test/java/com/compomics/coss/oglycans/PeptideGeneratorTest.java @@ -0,0 +1,70 @@ +package com.compomics.coss.oglycans; + +import com.compomics.oglycans.PeptideGenerator; +import com.compomics.util.experiment.biology.modifications.Modification; +import com.compomics.util.experiment.biology.modifications.ModificationCategory; +import com.compomics.util.experiment.biology.modifications.ModificationFactory; +import com.compomics.util.experiment.biology.modifications.ModificationType; +import com.compomics.util.experiment.biology.proteins.Peptide; +import com.compomics.util.experiment.biology.proteins.Protein; +import com.compomics.util.experiment.identification.protein_sequences.SingleProteinSequenceProvider; +import com.compomics.util.experiment.io.biology.protein.SequenceProvider; +import com.compomics.util.parameters.identification.advanced.SequenceMatchingParameters; +import com.compomics.util.parameters.identification.search.ModificationParameters; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.List; + +public class PeptideGeneratorTest { + + private PeptideGenerator peptideGenerator; + + @Before + public void initialize() { + List variableModifications = new ArrayList<>(); + + Modification oxidation = ModificationFactory.getInstance().getModification("Oxidation of M"); + Modification pyroGly = ModificationFactory.getInstance().getModification("Pyrolidone from E"); + // add O-glycans mod with TMT label to ModificationFactory + ArrayList residues = new ArrayList<>(); + residues.add("S"); + residues.add("T"); + Modification oglycan = new Modification(ModificationType.modaa, "oglycans", 503.3, residues, ModificationCategory.Common); + ModificationFactory.getInstance().addUserModification(oglycan); + + variableModifications.add(oglycan); + variableModifications.add(oxidation); + variableModifications.add(pyroGly); + + peptideGenerator = new PeptideGenerator(variableModifications); + } + + @Test + public void testReadPeptideFasta1() throws FileNotFoundException { + List peptides = peptideGenerator.readPeptideFasta(new File("src/test/resources/oglycans_test_1.fasta")); + + Assert.assertEquals(8, peptides.size()); + + // check the if a fixed modification is taken into account as well + ModificationParameters modificationParameters = new ModificationParameters(); + Modification carbo = ModificationFactory.getInstance().getModification("Carbamidomethylation of C"); + modificationParameters.addFixedModification(carbo); + Peptide peptide = peptides.get(0); + SequenceProvider sequenceProvider = new SingleProteinSequenceProvider(new Protein("TESTACCESSION", peptide.getSequence())); + String[] fixedModifications = peptide.getFixedModifications(modificationParameters, sequenceProvider, SequenceMatchingParameters.getDefaultSequenceMatching()); + Assert.assertEquals("Carbamidomethylation of C", fixedModifications[4]); + } + + @Test + public void testReadPeptideFasta2() throws FileNotFoundException { + List peptides = peptideGenerator.readPeptideFasta(new File("src/test/resources/oglycans_test_2.fasta")); + + Assert.assertEquals(8, peptides.size()); + } + +} diff --git a/src/test/resources/oglycans_test_1.fasta b/src/test/resources/oglycans_test_1.fasta new file mode 100644 index 0000000..006ce27 --- /dev/null +++ b/src/test/resources/oglycans_test_1.fasta @@ -0,0 +1,2 @@ +>0 +ESMC \ No newline at end of file diff --git a/src/test/resources/oglycans_test_2.fasta b/src/test/resources/oglycans_test_2.fasta new file mode 100644 index 0000000..659b02c --- /dev/null +++ b/src/test/resources/oglycans_test_2.fasta @@ -0,0 +1,2 @@ +>0 +EEKPAVTAAPSK \ No newline at end of file diff --git a/~$README.md b/~$README.md deleted file mode 100644 index 2bfd6a8..0000000 Binary files a/~$README.md and /dev/null differ