From 842713bcdcc9dabdc59c1f409d959f7e3b07d408 Mon Sep 17 00:00:00 2001 From: LukeCaruzo Date: Tue, 21 Nov 2017 10:06:03 +0100 Subject: [PATCH] Changed some from #73 and #72, #70 --- inst/java/deisotoper-1.0-SNAPSHOT.jar | Bin 74470 -> 73698 bytes .../proteomics/R/DataTransferObjectR.java | 8 +- .../R/FeaturesBasedDeisotoping.java | 61 ++--- .../R/FeaturesBasedDeisotopingMethodR.java | 102 ++++----- .../proteomics/R/MascotGenericFormatR.java | 8 +- .../java/ch/fgcz/proteomics/R/UtilitiesR.java | 12 +- .../main/java/ch/fgcz/proteomics/Version.java | 6 +- ...assSpectrometricMeasurementSerializer.java | 12 +- .../dto/MassSpectrometryMeasurement.java | 8 +- .../ch/fgcz/proteomics/fbdm/Deisotoper.java | 204 ++++++++--------- .../fgcz/proteomics/fbdm/IsotopicCluster.java | 22 +- .../proteomics/fbdm/IsotopicClusterGraph.java | 213 ++++++++++-------- .../proteomics/fbdm/IsotopicMassSpectrum.java | 33 ++- .../ch/fgcz/proteomics/fbdm/IsotopicSet.java | 123 +++++----- .../ch/fgcz/proteomics/fbdm/Peaklist.java | 6 +- .../java/ch/fgcz/proteomics/fbdm/Score.java | 20 +- .../java/ch/fgcz/proteomics/fbdm/Score5.java | 18 +- .../ch/fgcz/proteomics/fbdm/IsotopicTest.java | 140 ++++++------ 18 files changed, 508 insertions(+), 488 deletions(-) diff --git a/inst/java/deisotoper-1.0-SNAPSHOT.jar b/inst/java/deisotoper-1.0-SNAPSHOT.jar index 45db5d0f4fda5f6e7a31c40d7746679c8a524836..765ef54f13cb978881c889e79f577cb1cf7bd07f 100644 GIT binary patch delta 32628 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 aKZ4SO+aSJQNdTumf}%jlAiXUbkpBZtY&yvR delta 33498 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 m8 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 diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/DataTransferObjectR.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/DataTransferObjectR.java index ab181d6..5759f81 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/DataTransferObjectR.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/DataTransferObjectR.java @@ -8,15 +8,15 @@ import ch.fgcz.proteomics.dto.*; public class DataTransferObjectR { - public static String serializeMSMToJsonR(String filename, MassSpectrometryMeasurement m) { - return MassSpectrometricMeasurementSerializer.serializeToJson(filename, m); + public static String serializeMSMToJsonR(String filename, MassSpectrometryMeasurement massspectrometrymeasurement) { + return MassSpectrometricMeasurementSerializer.serializeToJson(filename, massspectrometrymeasurement); } public static MassSpectrometryMeasurement deserializeJsonToMSMR(String filename) { return MassSpectrometricMeasurementSerializer.deserializeFromJson(filename); } - public static MassSpectrometryMeasurement massSpectrometryMeasurementR(String src) { - return new MassSpectrometryMeasurement(src); + public static MassSpectrometryMeasurement massSpectrometryMeasurementR(String source) { + return new MassSpectrometryMeasurement(source); } } \ No newline at end of file diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/FeaturesBasedDeisotoping.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/FeaturesBasedDeisotoping.java index a381990..2bcda3c 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/FeaturesBasedDeisotoping.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/FeaturesBasedDeisotoping.java @@ -21,8 +21,8 @@ public class FeaturesBasedDeisotoping { private Deisotoper deisotoper = new Deisotoper(); - private MassSpectrum massSpectrum = new MassSpectrum(); - private MassSpectrum resultSpectrum = new MassSpectrum(); + private MassSpectrum massspectrum = new MassSpectrum(); + private MassSpectrum resultspectrum = new MassSpectrum(); public void setConfiguration(double[] AA_MASS, double F1, double F2, double F3, double F4, double F5, double DELTA, double ERRORTOLERANCE, double DISTANCE, double NOISE, boolean DECHARGE) { @@ -52,7 +52,7 @@ public void setMz(double[] mz) { mzlist.add(mz[i]); } - this.massSpectrum.setMz(mzlist); + this.massspectrum.setMz(mzlist); } public void setIntensity(double[] intensity) { @@ -61,35 +61,35 @@ public void setIntensity(double[] intensity) { intensitylist.add(intensity[i]); } - this.massSpectrum.setIntensity(intensitylist); + this.massspectrum.setIntensity(intensitylist); } public void setPepMass(double pepmass) { - this.massSpectrum.setPeptideMass(pepmass); + this.massspectrum.setPeptideMass(pepmass); } public void setCharge(int charge) { - this.massSpectrum.setChargeState(charge); + this.massspectrum.setChargeState(charge); } public double[] getMz() { - return this.resultSpectrum.getMzArray(); + return this.resultspectrum.getMzArray(); } public double[] getIntensity() { - return this.resultSpectrum.getIntensityArray(); + return this.resultspectrum.getIntensityArray(); } public void deisotope(String modus) { - this.resultSpectrum = this.deisotoper.deisotopeMS(massSpectrum, modus); + this.resultspectrum = this.deisotoper.deisotopeMS(massspectrum, modus); } public String[] getDOT() { - String[] dotgraphs = new String[this.deisotoper.getIcgList().size()]; + String[] dotgraphs = new String[this.deisotoper.getIsotopicClusterGraphList().size()]; int i = 0; - for (IsotopicClusterGraph icg : this.deisotoper.getIcgList()) { - dotgraphs[i] = icg.toDOTGraph(); + for (IsotopicClusterGraph isotopicclustergraph : this.deisotoper.getIsotopicClusterGraphList()) { + dotgraphs[i] = isotopicclustergraph.toDOTGraph(); i++; } @@ -101,48 +101,49 @@ public String getAnnotatedSpectrum() { } public String getSummary() { - MassSpectrum ms = this.massSpectrum; + MassSpectrum massspectrum = this.massspectrum; int numberis = 0; int numberic = 0; int numberipeaks = 0; int numberpeaks = 0; - numberpeaks += ms.getMz().size(); + numberpeaks += massspectrum.getMz().size(); - IsotopicMassSpectrum ims = new IsotopicMassSpectrum(ms, this.deisotoper.getConfiguration().getDelta(), - this.deisotoper.getConfiguration()); + IsotopicMassSpectrum isotopicmassspectrum = new IsotopicMassSpectrum(massspectrum, + this.deisotoper.getConfiguration().getDelta(), this.deisotoper.getConfiguration(), this.deisotoper); - numberis += ims.getIsotopicMassSpectrum().size(); + numberis += isotopicmassspectrum.getIsotopicMassSpectrum().size(); - for (IsotopicSet is : ims.getIsotopicMassSpectrum()) { - numberic += is.getIsotopicSet().size(); + for (IsotopicSet isotopicset : isotopicmassspectrum.getIsotopicMassSpectrum()) { + numberic += isotopicset.getIsotopicSet().size(); List peakic = new ArrayList<>(); - for (IsotopicCluster ic : is.getIsotopicSet()) { - if (ic.getIsotopicCluster() != null) { - peakic.addAll(ic.getIsotopicCluster()); + for (IsotopicCluster isotopiccluster : isotopicset.getIsotopicSet()) { + if (isotopiccluster.getIsotopicCluster() != null) { + peakic.addAll(isotopiccluster.getIsotopicCluster()); } } - Set titles = new HashSet(); + Set set = new HashSet(); List result = new ArrayList(); - for (Peak p : peakic) { - if (titles.add(p.getMz())) { - result.add(p); + for (Peak peak : peakic) { + if (set.add(peak.getMz())) { + result.add(peak); } } numberipeaks += result.size(); } - StringBuilder sb = new StringBuilder(); + StringBuilder stringbuilder = new StringBuilder(); String linesep = System.getProperty("line.separator"); - sb.append("NumberOfIsotopicSets,NumberOfIsotopicClusters,NumberOfPeaksInIsotopicClusters,NumberOfPeaks") + stringbuilder + .append("NumberOfIsotopicSets,NumberOfIsotopicClusters,NumberOfPeaksInIsotopicClusters,NumberOfPeaks") .append(linesep); - sb.append(numberis).append(",").append(numberic).append(",").append(numberipeaks).append(",") + stringbuilder.append(numberis).append(",").append(numberic).append(",").append(numberipeaks).append(",") .append(numberpeaks).append(linesep); - return sb.toString(); + return stringbuilder.toString(); } } \ No newline at end of file diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/FeaturesBasedDeisotopingMethodR.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/FeaturesBasedDeisotopingMethodR.java index 5c2eab6..36c48df 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/FeaturesBasedDeisotopingMethodR.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/FeaturesBasedDeisotopingMethodR.java @@ -6,20 +6,10 @@ */ import java.util.ArrayList; -import java.util.HashSet; import java.util.List; -import java.util.Set; -import ch.fgcz.proteomics.dto.MassSpectrometryMeasurement; -import ch.fgcz.proteomics.dto.MassSpectrum; import ch.fgcz.proteomics.fbdm.Configuration; -import ch.fgcz.proteomics.fbdm.IsotopicClusterGraph; -import ch.fgcz.proteomics.fbdm.IsotopicMassSpectrum; -import ch.fgcz.proteomics.fbdm.IsotopicSet; -import ch.fgcz.proteomics.fbdm.IsotopicCluster; -import ch.fgcz.proteomics.fbdm.Peak; -import ch.fgcz.proteomics.fbdm.Peaklist; public class FeaturesBasedDeisotopingMethodR { // public static MassSpectrometryMeasurement @@ -59,51 +49,53 @@ public class FeaturesBasedDeisotopingMethodR { // return icg.toDOTGraph(); // } - public static String getStatistic(MassSpectrometryMeasurement msm, Configuration config) { - int numberms = msm.getMSlist().size(); - int numberis = 0; - int numberic = 0; - int numberipeaks = 0; - int numberpeaks = 0; - - for (MassSpectrum ms : msm.getMSlist()) { - numberpeaks += ms.getMz().size(); - - IsotopicMassSpectrum ims = new IsotopicMassSpectrum(ms, config.getDelta(), config); - - numberis += ims.getIsotopicMassSpectrum().size(); - - for (IsotopicSet is : ims.getIsotopicMassSpectrum()) { - numberic += is.getIsotopicSet().size(); - List peakic = new ArrayList<>(); - - for (IsotopicCluster ic : is.getIsotopicSet()) { - peakic.addAll(ic.getIsotopicCluster()); - } - - Set titles = new HashSet(); - List result = new ArrayList(); - - for (Peak p : peakic) { - if (titles.add(p.getMz())) { - result.add(p); - } - } - - numberipeaks += result.size(); - } - } - - StringBuilder sb = new StringBuilder(); - String linesep = System.getProperty("line.separator"); - sb.append( - "NumberOfMassSpectra,NumberOfIsotopicSets,NumberOfIsotopicClusters,NumberOfPeaksInIsotopicClusters,NumberOfPeaks") - .append(linesep); - sb.append(numberms).append(",").append(numberis).append(",").append(numberic).append(",").append(numberipeaks) - .append(",").append(numberpeaks).append(linesep); - - return sb.toString(); - } + // public static String getStatistic(MassSpectrometryMeasurement msm, + // Configuration config) { + // int numberms = msm.getMSlist().size(); + // int numberis = 0; + // int numberic = 0; + // int numberipeaks = 0; + // int numberpeaks = 0; + // + // for (MassSpectrum ms : msm.getMSlist()) { + // numberpeaks += ms.getMz().size(); + // + // IsotopicMassSpectrum ims = new IsotopicMassSpectrum(ms, config.getDelta(), + // config); + // + // numberis += ims.getIsotopicMassSpectrum().size(); + // + // for (IsotopicSet is : ims.getIsotopicMassSpectrum()) { + // numberic += is.getIsotopicSet().size(); + // List peakic = new ArrayList<>(); + // + // for (IsotopicCluster ic : is.getIsotopicSet()) { + // peakic.addAll(ic.getIsotopicCluster()); + // } + // + // Set titles = new HashSet(); + // List result = new ArrayList(); + // + // for (Peak p : peakic) { + // if (titles.add(p.getMz())) { + // result.add(p); + // } + // } + // + // numberipeaks += result.size(); + // } + // } + // + // StringBuilder sb = new StringBuilder(); + // String linesep = System.getProperty("line.separator"); + // sb.append( + // "NumberOfMassSpectra,NumberOfIsotopicSets,NumberOfIsotopicClusters,NumberOfPeaksInIsotopicClusters,NumberOfPeaks") + // .append(linesep); + // sb.append(numberms).append(",").append(numberis).append(",").append(numberic).append(",").append(numberipeaks) + // .append(",").append(numberpeaks).append(linesep); + // + // return sb.toString(); + // } public static Configuration createConfigurationR(double[] aa, double F1, double F2, double F3, double F4, double F5, double DELTA, double ERRORTOLERANCE, double DISTANCE, double NOISE, boolean DECHARGE) { diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/MascotGenericFormatR.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/MascotGenericFormatR.java index 37e3442..6d99d89 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/MascotGenericFormatR.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/MascotGenericFormatR.java @@ -10,11 +10,11 @@ import ch.fgcz.proteomics.mgf.WriteMGF; public class MascotGenericFormatR { - public static MassSpectrometryMeasurement readR(String file) { - return ReadMGF.read(file); + public static MassSpectrometryMeasurement readR(String filename) { + return ReadMGF.read(filename); } - public static boolean writeR(String file, MassSpectrometryMeasurement msm) { - return WriteMGF.write(file, msm); + public static boolean writeR(String filename, MassSpectrometryMeasurement massspectrometrymeasurement) { + return WriteMGF.write(filename, massspectrometrymeasurement); } } diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/UtilitiesR.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/UtilitiesR.java index 706feb5..79c2d63 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/UtilitiesR.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/R/UtilitiesR.java @@ -11,17 +11,17 @@ import ch.fgcz.proteomics.utilities.Summary; public class UtilitiesR { - public static double[] findNNR(double[] vec, double[] q) { - return FindNearestNeighbor.findNN(vec, q); + public static double[] findNNR(double[] vector, double[] query) { + return FindNearestNeighbor.findNN(vector, query); } - public static String summaryMSMR(MassSpectrometryMeasurement m) { - return Summary.makeSummary(m); + public static String summaryMSMR(MassSpectrometryMeasurement massspectrometrymeasurement) { + return Summary.makeSummary(massspectrometrymeasurement); } - public static String summaryMSR(MassSpectrum m) { + public static String summaryMSR(MassSpectrum massspectrum) { MassSpectrometryMeasurement msm = new MassSpectrometryMeasurement(""); - msm.getMSlist().add(m); + msm.getMSlist().add(massspectrum); return Summary.makeSummary(msm); } diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/Version.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/Version.java index 9eb46e8..596a61f 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/Version.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/Version.java @@ -7,11 +7,11 @@ public class Version { private static String versionOfDTO() { - return "Java Package: DTO, Date: 2017-11-16, Author: Lucas Schmidt"; + return "Java Package: DTO, Date: 2017-11-21, Author: Lucas Schmidt"; } private static String versionOfFBDM() { - return "Java Package: FBDM, Date: 2017-11-20, Author: Lucas Schmidt"; + return "Java Package: FBDM, Date: 2017-11-21, Author: Lucas Schmidt"; } private static String versionOfMSPY() { @@ -23,7 +23,7 @@ private static String versionOfMGF() { } private static String versionOfRAdapter() { - return "Java Package: RAdapter, Date: 2017-11-20, Author: Lucas Schmidt"; + return "Java Package: RAdapter, Date: 2017-11-21, Author: Lucas Schmidt"; } private static String versionOfUtilities() { diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/dto/MassSpectrometricMeasurementSerializer.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/dto/MassSpectrometricMeasurementSerializer.java index 87496c9..4f0f496 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/dto/MassSpectrometricMeasurementSerializer.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/dto/MassSpectrometricMeasurementSerializer.java @@ -15,10 +15,10 @@ import com.google.gson.reflect.TypeToken; public class MassSpectrometricMeasurementSerializer { - public static String serializeToJson(String filename, MassSpectrometryMeasurement msm) { + public static String serializeToJson(String filename, MassSpectrometryMeasurement massspectrometrymeasurement) { Gson gson = new Gson(); - String data = gson.toJson(msm); + String data = gson.toJson(massspectrometrymeasurement); try (PrintWriter out = new PrintWriter(filename)) { out.println(data); @@ -35,15 +35,15 @@ public static MassSpectrometryMeasurement deserializeFromJson(String filename) { String data = null; try (BufferedReader br = new BufferedReader(new FileReader(filename))) { - StringBuilder sb = new StringBuilder(); + StringBuilder stringbuilder = new StringBuilder(); String line = br.readLine(); while (line != null) { - sb.append(line); - sb.append(System.lineSeparator()); + stringbuilder.append(line); + stringbuilder.append(System.lineSeparator()); line = br.readLine(); } - data = sb.toString(); + data = stringbuilder.toString(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/dto/MassSpectrometryMeasurement.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/dto/MassSpectrometryMeasurement.java index 11e127c..83daf7e 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/dto/MassSpectrometryMeasurement.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/dto/MassSpectrometryMeasurement.java @@ -9,7 +9,7 @@ import java.util.List; public class MassSpectrometryMeasurement { - private List mslist = new ArrayList<>(); + private List massspectrumlist = new ArrayList<>(); private String source; public String getSource() { @@ -21,11 +21,11 @@ public void setSource(String source) { } public List getMSlist() { - return mslist; + return massspectrumlist; } - public void setMSlist(List list) { - this.mslist = list; + public void setMSlist(List massspectrumlist) { + this.massspectrumlist = massspectrumlist; } public MassSpectrometryMeasurement(String source) { diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Deisotoper.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Deisotoper.java index ed47e28..361e9dd 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Deisotoper.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Deisotoper.java @@ -9,16 +9,14 @@ import java.util.Collections; import java.util.List; -import org.jgrapht.GraphPath; // TODO (LS): - remove this dependency - import ch.fgcz.proteomics.dto.MassSpectrometryMeasurement; import ch.fgcz.proteomics.dto.MassSpectrum; import ch.fgcz.proteomics.utilities.Sort; public class Deisotoper { private Configuration config; - private List icglist = new ArrayList<>(); - private String annotatedSpectrum; + private List isotopicclustergraphlist = new ArrayList<>(); + private String annotatedspectrum; public Configuration getConfiguration() { return config; @@ -28,182 +26,166 @@ public void setConfiguration(Configuration config) { this.config = config; } - // TODO (LS): do not use acronyms - public List getIcgList() { - return icglist; + public List getIsotopicClusterGraphList() { + return isotopicclustergraphlist; } public String getAnnotatedSpectrum() { - return annotatedSpectrum; + return annotatedspectrum; } - // TODO (LS): not used remove - public MassSpectrometryMeasurement deisotopeMSM(MassSpectrometryMeasurement input, String modus, - Configuration config) { - MassSpectrometryMeasurement output = new MassSpectrometryMeasurement(input.getSource()); + public void setAnnotatedSpectrum(String annotatedspectrum) { + this.annotatedspectrum = annotatedspectrum; + } + + public MassSpectrometryMeasurement deisotopeMSM(MassSpectrometryMeasurement massspectrometrymeasurementin, + String modus, Configuration config) { + MassSpectrometryMeasurement massspectrometrymeasurementout = new MassSpectrometryMeasurement( + massspectrometrymeasurementin.getSource()); this.config = config; - for (MassSpectrum ms : input.getMSlist()) { - output.getMSlist().add(deisotopeMS(ms, modus)); + for (MassSpectrum massspectrum : massspectrometrymeasurementin.getMSlist()) { + massspectrometrymeasurementout.getMSlist().add(deisotopeMS(massspectrum, modus)); } - return output; + return massspectrometrymeasurementout; } - // TODO (LS) : - public MassSpectrum deisotopeMS(MassSpectrum massSpectrum, String modus) { - IsotopicMassSpectrum ims = new IsotopicMassSpectrum(massSpectrum, this.config.getDelta(), this.config); - - saveAnnotatedSpectrum(ims); + public MassSpectrum deisotopeMS(MassSpectrum massspectrum, String modus) { + IsotopicMassSpectrum isotopicmassspectrum = new IsotopicMassSpectrum(massspectrum, this.config.getDelta(), + this.config, this); - //TODO (LS) : move this method to IsotopicSet - ListMassSpectrum list = makeGraph(massSpectrum, ims, modus); + // TODO (LS) : move this method to IsotopicSet + ListMassSpectrum listmassspectrumaggregated = aggretaion(massspectrum, isotopicmassspectrum, modus); - ListMassSpectrum list3 = decharge(list, this.config); + ListMassSpectrum listmassspectrumdecharged = decharge(listmassspectrumaggregated, this.config); - Sort.keySort(list3.getMz(), list3.getMz(), list3.getIntensity(), list3.getIsotope(), list3.getCharge()); + Sort.keySort(listmassspectrumdecharged.getMz(), listmassspectrumdecharged.getMz(), + listmassspectrumdecharged.getIntensity(), listmassspectrumdecharged.getIsotope(), + listmassspectrumdecharged.getCharge()); - MassSpectrum msdeisotoped = noiseFiltering(massSpectrum, list3, this.config); + MassSpectrum massspectrumdeisotoped = noiseFiltering(massspectrum, listmassspectrumdecharged, this.config); - return msdeisotoped; + return massspectrumdeisotoped; } - private MassSpectrum noiseFiltering(MassSpectrum massSpectrum, ListMassSpectrum list, Configuration config) { - MassSpectrum msdeisotoped; + private MassSpectrum noiseFiltering(MassSpectrum massspectrum, ListMassSpectrum listmassspectrum, + Configuration config) { + MassSpectrum massspectrundeisotoped; + if (config.getNoise() != 0) { - double threshold = Collections.max(list.getIntensity()) * config.getNoise() / 100; + double threshold = Collections.max(listmassspectrum.getIntensity()) * config.getNoise() / 100; List mz5 = new ArrayList<>(); List intensity5 = new ArrayList<>(); List isotope5 = new ArrayList<>(); List charge5 = new ArrayList<>(); - for (int i = 0; i < list.getIntensity().size(); i++) { - if (threshold < list.getIntensity().get(i)) { - mz5.add(list.getMz().get(i)); - intensity5.add(list.getIntensity().get(i)); - isotope5.add(list.getIsotope().get(i)); - charge5.add(list.getCharge().get(i)); + for (int i = 0; i < listmassspectrum.getIntensity().size(); i++) { + if (threshold < listmassspectrum.getIntensity().get(i)) { + mz5.add(listmassspectrum.getMz().get(i)); + intensity5.add(listmassspectrum.getIntensity().get(i)); + isotope5.add(listmassspectrum.getIsotope().get(i)); + charge5.add(listmassspectrum.getCharge().get(i)); } } - msdeisotoped = new MassSpectrum(massSpectrum.getTyp(), massSpectrum.getSearchEngine(), mz5, intensity5, massSpectrum.getPeptideMass(), - massSpectrum.getRt(), massSpectrum.getChargeState(), massSpectrum.getId(), charge5, isotope5); + massspectrundeisotoped = new MassSpectrum(massspectrum.getTyp(), massspectrum.getSearchEngine(), mz5, + intensity5, massspectrum.getPeptideMass(), massspectrum.getRt(), massspectrum.getChargeState(), + massspectrum.getId(), charge5, isotope5); } else { - msdeisotoped = new MassSpectrum(massSpectrum.getTyp(), massSpectrum.getSearchEngine(), list.getMz(), list.getIntensity(), - massSpectrum.getPeptideMass(), massSpectrum.getRt(), massSpectrum.getChargeState(), massSpectrum.getId(), list.getCharge(), - list.getIsotope()); + massspectrundeisotoped = new MassSpectrum(massspectrum.getTyp(), massspectrum.getSearchEngine(), + listmassspectrum.getMz(), listmassspectrum.getIntensity(), massspectrum.getPeptideMass(), + massspectrum.getRt(), massspectrum.getChargeState(), massspectrum.getId(), + listmassspectrum.getCharge(), listmassspectrum.getIsotope()); } - return msdeisotoped; - } + return massspectrundeisotoped; + } - // TODO (LS) operations on paths should only happen in IsotopicSet. - private ListMassSpectrum makeGraph(MassSpectrum input, IsotopicMassSpectrum ims, String modus) { - this.icglist.removeAll(this.icglist); + private ListMassSpectrum aggretaion(MassSpectrum massspectrumin, IsotopicMassSpectrum isotopicmassspectrum, + String modus) { + this.isotopicclustergraphlist.removeAll(this.isotopicclustergraphlist); - ListMassSpectrum list = new ListMassSpectrum(); + ListMassSpectrum listmassspectrumaggregated = new ListMassSpectrum(); List mz = new ArrayList<>(); - for (IsotopicSet is : ims.getIsotopicMassSpectrum()) { + for (IsotopicSet isotopicset : isotopicmassspectrum.getIsotopicMassSpectrum()) { - GraphPath bp = is.getBestPath(); + List bestpath = isotopicset.getBestPath(); - this.icglist.add(is.getIcg()); + this.isotopicclustergraphlist.add(isotopicset.getIsotopicClusterGraph()); - ListMassSpectrum list2 = new ListMassSpectrum(); + ListMassSpectrum listmassspectrumaggregated2 = new ListMassSpectrum(); List mz2 = new ArrayList<>(); - for (IsotopicCluster cluster : bp.getVertexList()) { + for (IsotopicCluster cluster : bestpath) { if (cluster.getIsotopicCluster() != null) { - for (Peak p : cluster.getIsotopicCluster()) { - mz2.add(p.getMz()); + for (Peak peak : cluster.getIsotopicCluster()) { + mz2.add(peak.getMz()); } cluster.aggregation(modus); int position = 1; - for (Peak p : cluster.getIsotopicCluster()) { - list2.getMz().add(p.getMz()); - list2.getIntensity().add(p.getIntensity()); - list2.getIsotope().add((double) position); - list2.getCharge().add(cluster.getCharge()); + for (Peak peak : cluster.getIsotopicCluster()) { + listmassspectrumaggregated2.getMz().add(peak.getMz()); + listmassspectrumaggregated2.getIntensity().add(peak.getIntensity()); + listmassspectrumaggregated2.getIsotope().add((double) position); + listmassspectrumaggregated2.getCharge().add(cluster.getCharge()); position++; } } } - list.getMz().addAll(list2.getMz()); - list.getIntensity().addAll(list2.getIntensity()); - list.getIsotope().addAll(list2.getIsotope()); - list.getCharge().addAll(list2.getCharge()); + listmassspectrumaggregated.getMz().addAll(listmassspectrumaggregated2.getMz()); + listmassspectrumaggregated.getIntensity().addAll(listmassspectrumaggregated2.getIntensity()); + listmassspectrumaggregated.getIsotope().addAll(listmassspectrumaggregated2.getIsotope()); + listmassspectrumaggregated.getCharge().addAll(listmassspectrumaggregated2.getCharge()); mz.addAll(mz2); } - for (int i = 0; i < input.getMz().size(); i++) { - if (!mz.contains(input.getMz().get(i))) { - list.getMz().add(input.getMz().get(i)); - list.getIntensity().add(input.getIntensity().get(i)); - list.getIsotope().add(-1.0); - list.getCharge().add(-1); - } - } - - return list; - } - - // TODO (LS) This is a method of the class IsotopicMassSpectrum - private void saveAnnotatedSpectrum(IsotopicMassSpectrum ims) { - this.annotatedSpectrum = null; - - StringBuilder sb = new StringBuilder(); - String linesep = System.getProperty("line.separator"); - - sb.append("IsotopicSet,IsotopicCluster,Peak,Charge,mZ,Intensity").append(linesep); - - for (IsotopicSet is : ims.getIsotopicMassSpectrum()) { - for (IsotopicCluster ic : is.getIsotopicSet()) { - if (ic.getIsotopicCluster() != null) { - for (Peak p : ic.getIsotopicCluster()) { - sb.append(is.getSetID()).append(",").append(ic.getClusterID()).append(",").append(p.getPeakID()) - .append(",").append(ic.getCharge()).append(",").append(p.getMz()).append(",") - .append(p.getIntensity()).append(linesep); - } - } + for (int i = 0; i < massspectrumin.getMz().size(); i++) { + if (!mz.contains(massspectrumin.getMz().get(i))) { + listmassspectrumaggregated.getMz().add(massspectrumin.getMz().get(i)); + listmassspectrumaggregated.getIntensity().add(massspectrumin.getIntensity().get(i)); + listmassspectrumaggregated.getIsotope().add(-1.0); + listmassspectrumaggregated.getCharge().add(-1); } } - this.annotatedSpectrum = sb.toString(); + return listmassspectrumaggregated; } - private ListMassSpectrum decharge(ListMassSpectrum list, Configuration config) { - ListMassSpectrum list2 = new ListMassSpectrum(); + private ListMassSpectrum decharge(ListMassSpectrum listmassspectrum, Configuration config) { + ListMassSpectrum listmassspectrumdecharged = new ListMassSpectrum(); if (config.isDecharge() == true) { - for (int i = 0; i < list.getMz().size(); i++) { - if (list.getCharge().get(i) > 1) { - list2.getMz().add(list.getMz().get(i) * list.getCharge().get(i) - - (list.getCharge().get(i) - 1) * config.getH_MASS()); - list2.getIntensity().add(list.getIntensity().get(i)); - list2.getIsotope().add(list.getIsotope().get(i)); - list2.getCharge().add(1); + for (int i = 0; i < listmassspectrum.getMz().size(); i++) { + if (listmassspectrum.getCharge().get(i) > 1) { + listmassspectrumdecharged.getMz() + .add(listmassspectrum.getMz().get(i) * listmassspectrum.getCharge().get(i) + - (listmassspectrum.getCharge().get(i) - 1) * config.getH_MASS()); + listmassspectrumdecharged.getIntensity().add(listmassspectrum.getIntensity().get(i)); + listmassspectrumdecharged.getIsotope().add(listmassspectrum.getIsotope().get(i)); + listmassspectrumdecharged.getCharge().add(1); } else { - list2.getMz().add(list.getMz().get(i)); - list2.getIntensity().add(list.getIntensity().get(i)); - list2.getIsotope().add(list.getIsotope().get(i)); - list2.getCharge().add(list.getCharge().get(i)); + listmassspectrumdecharged.getMz().add(listmassspectrum.getMz().get(i)); + listmassspectrumdecharged.getIntensity().add(listmassspectrum.getIntensity().get(i)); + listmassspectrumdecharged.getIsotope().add(listmassspectrum.getIsotope().get(i)); + listmassspectrumdecharged.getCharge().add(listmassspectrum.getCharge().get(i)); } } } else { - list2.getMz().addAll(list.getMz()); - list2.getIntensity().addAll(list.getIntensity()); - list2.getIsotope().addAll(list.getIsotope()); - list2.getCharge().addAll(list.getCharge()); + listmassspectrumdecharged.getMz().addAll(listmassspectrum.getMz()); + listmassspectrumdecharged.getIntensity().addAll(listmassspectrum.getIntensity()); + listmassspectrumdecharged.getIsotope().addAll(listmassspectrum.getIsotope()); + listmassspectrumdecharged.getCharge().addAll(listmassspectrum.getCharge()); } - return list2; + return listmassspectrumdecharged; } } \ No newline at end of file diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicCluster.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicCluster.java index 6984930..25431f1 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicCluster.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicCluster.java @@ -77,10 +77,10 @@ public IsotopicCluster aggregateHighest() { double minint = 0; double minmz = 0; - for (Peak p : this.isotopiccluster) { - if (p.getIntensity() > minint) { - minint = p.getIntensity(); - minmz = p.getMz(); + for (Peak peak : this.isotopiccluster) { + if (peak.getIntensity() > minint) { + minint = peak.getIntensity(); + minmz = peak.getMz(); } } @@ -98,8 +98,8 @@ public IsotopicCluster aggregateHighest() { private double sumIntensity() { double intensitysum = 0; - for (Peak p : this.isotopiccluster) { - intensitysum += p.getIntensity(); + for (Peak peak : this.isotopiccluster) { + intensitysum += peak.getIntensity(); } return intensitysum; @@ -119,16 +119,16 @@ public IsotopicCluster aggregation(String modus) { @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("(" + this.clusterID + ") [ "); + StringBuilder stringbuilder = new StringBuilder(); + stringbuilder.append("(" + this.clusterID + ") [ "); if (this.isotopiccluster == null) { return this.status; } for (Peak p : this.isotopiccluster) { - sb.append(p.getMz() + " "); + stringbuilder.append(p.getMz() + " "); } - sb.append("]"); - return sb.toString(); + stringbuilder.append("]"); + return stringbuilder.toString(); } private static void rangeCheck(List peaks, Configuration config, int charge) throws Exception { diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicClusterGraph.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicClusterGraph.java index 70154a8..08c49a6 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicClusterGraph.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicClusterGraph.java @@ -15,7 +15,7 @@ import java.util.Set; public class IsotopicClusterGraph { - private double min = Double.MAX_VALUE; + private double minimum = Double.MAX_VALUE; private DefaultDirectedWeightedGraph isotopicclustergraph = new DefaultDirectedWeightedGraph( Connection.class); @@ -28,182 +28,199 @@ public void setIsotopicclustergraph( this.isotopicclustergraph = isotopicclustergraph; } - public GraphPath bestPath(IsotopicCluster source, IsotopicCluster sink) { - KShortestPaths paths = new KShortestPaths<>(this.isotopicclustergraph, 999999); + public GraphPath bestPath(IsotopicCluster startcluster, IsotopicCluster endcluster) { + KShortestPaths allpaths = new KShortestPaths<>(this.isotopicclustergraph, 999999); - List> path = paths.getPaths(source, sink); + List> paths = allpaths.getPaths(startcluster, endcluster); Set weights = new HashSet(); - for (GraphPath p : path) { - weights.add(p.getWeight()); + for (GraphPath path : paths) { + weights.add(path.getWeight()); } - if (weights.size() == 1 && path.size() != 1) { + if (weights.size() == 1 && paths.size() != 1) { System.err.println( "WARNING: All scores are the same, therefore there is no valid best path! Please check if your input mass spectrum is correct! This could have a minimal impact on the results."); } - return path.get(path.size() - 1); + return paths.get(paths.size() - 1); } public String toDOTGraph() { - StringBuilder sb = new StringBuilder(); + StringBuilder stringbuilder = new StringBuilder(); String linesep = System.getProperty("line.separator"); - sb.append("digraph {").append(linesep); - sb.append("rankdir=LR;").append(linesep); - sb.append("node [shape=box];").append(linesep); - - for (Connection e : this.isotopicclustergraph.edgeSet()) { - if (this.isotopicclustergraph.getEdgeSource(e).getIsotopicCluster() != null - && this.isotopicclustergraph.getEdgeTarget(e).getIsotopicCluster() != null) { - sb.append("\"(" + this.isotopicclustergraph.getEdgeSource(e).getClusterID() + ") [ "); - for (Peak x : this.isotopicclustergraph.getEdgeSource(e).getIsotopicCluster()) { - sb.append(" (" + x.getPeakID() + ") " + Math.round(x.getMz() * 100d) / 100d + " "); + stringbuilder.append("digraph {").append(linesep); + stringbuilder.append("rankdir=LR;").append(linesep); + stringbuilder.append("node [shape=box];").append(linesep); + + for (Connection connection : this.isotopicclustergraph.edgeSet()) { + if (this.isotopicclustergraph.getEdgeSource(connection).getIsotopicCluster() != null + && this.isotopicclustergraph.getEdgeTarget(connection).getIsotopicCluster() != null) { + stringbuilder + .append("\"(" + this.isotopicclustergraph.getEdgeSource(connection).getClusterID() + ") [ "); + for (Peak peak : this.isotopicclustergraph.getEdgeSource(connection).getIsotopicCluster()) { + stringbuilder.append(" (" + peak.getPeakID() + ") " + Math.round(peak.getMz() * 100d) / 100d + " "); } - sb.append("] z:" + this.isotopicclustergraph.getEdgeSource(e).getCharge() + "\" -> \"(" - + this.isotopicclustergraph.getEdgeTarget(e).getClusterID() + ") [ "); - for (Peak x : this.isotopicclustergraph.getEdgeTarget(e).getIsotopicCluster()) { - sb.append(" (" + x.getPeakID() + ") " + Math.round(x.getMz() * 100d) / 100d + " "); + stringbuilder.append("] z:" + this.isotopicclustergraph.getEdgeSource(connection).getCharge() + + "\" -> \"(" + this.isotopicclustergraph.getEdgeTarget(connection).getClusterID() + ") [ "); + for (Peak peak : this.isotopicclustergraph.getEdgeTarget(connection).getIsotopicCluster()) { + stringbuilder.append(" (" + peak.getPeakID() + ") " + Math.round(peak.getMz() * 100d) / 100d + " "); } - sb.append("] z:" + this.isotopicclustergraph.getEdgeTarget(e).getCharge() + "\"") - .append("[color=\"" + e.getColor() + "\",label=\"" + Math.round(e.getScore() * 10000d) / 10000d - + "\",weight=\"" + e.getScore() + "\"];") + stringbuilder.append("] z:" + this.isotopicclustergraph.getEdgeTarget(connection).getCharge() + "\"") + .append("[color=\"" + connection.getColor() + "\",label=\"" + + Math.round(connection.getScore() * 10000d) / 10000d + "\",weight=\"" + + connection.getScore() + "\"];") .append(linesep); - } else if (this.isotopicclustergraph.getEdgeSource(e).getIsotopicCluster() == null - && this.isotopicclustergraph.getEdgeTarget(e).getIsotopicCluster() != null) { - sb.append(this.isotopicclustergraph.getEdgeSource(e).getStatus()); - sb.append(" -> \"(" + this.isotopicclustergraph.getEdgeTarget(e).getClusterID() + ") [ "); - for (Peak x : this.isotopicclustergraph.getEdgeTarget(e).getIsotopicCluster()) { - sb.append(" (" + x.getPeakID() + ") " + Math.round(x.getMz() * 100d) / 100d + " "); + } else if (this.isotopicclustergraph.getEdgeSource(connection).getIsotopicCluster() == null + && this.isotopicclustergraph.getEdgeTarget(connection).getIsotopicCluster() != null) { + stringbuilder.append(this.isotopicclustergraph.getEdgeSource(connection).getStatus()); + stringbuilder.append( + " -> \"(" + this.isotopicclustergraph.getEdgeTarget(connection).getClusterID() + ") [ "); + for (Peak peak : this.isotopicclustergraph.getEdgeTarget(connection).getIsotopicCluster()) { + stringbuilder.append(" (" + peak.getPeakID() + ") " + Math.round(peak.getMz() * 100d) / 100d + " "); } - sb.append("] z:" + this.isotopicclustergraph.getEdgeTarget(e).getCharge() + "\"") - .append("[color=\"" + e.getColor() + "\",label=\"" + Math.round(e.getScore() * 10000d) / 10000d - + "\",weight=\"" + e.getScore() + "\"];") + stringbuilder.append("] z:" + this.isotopicclustergraph.getEdgeTarget(connection).getCharge() + "\"") + .append("[color=\"" + connection.getColor() + "\",label=\"" + + Math.round(connection.getScore() * 10000d) / 10000d + "\",weight=\"" + + connection.getScore() + "\"];") .append(linesep); - } else if (this.isotopicclustergraph.getEdgeTarget(e).getIsotopicCluster() == null - && this.isotopicclustergraph.getEdgeSource(e).getIsotopicCluster() != null) { - sb.append("\"(" + this.isotopicclustergraph.getEdgeSource(e).getClusterID() + ") [ "); - for (Peak x : this.isotopicclustergraph.getEdgeSource(e).getIsotopicCluster()) { - sb.append(" (" + x.getPeakID() + ") " + Math.round(x.getMz() * 100d) / 100d + " "); + } else if (this.isotopicclustergraph.getEdgeTarget(connection).getIsotopicCluster() == null + && this.isotopicclustergraph.getEdgeSource(connection).getIsotopicCluster() != null) { + stringbuilder + .append("\"(" + this.isotopicclustergraph.getEdgeSource(connection).getClusterID() + ") [ "); + for (Peak peak : this.isotopicclustergraph.getEdgeSource(connection).getIsotopicCluster()) { + stringbuilder.append(" (" + peak.getPeakID() + ") " + Math.round(peak.getMz() * 100d) / 100d + " "); } - sb.append("] z:" + this.isotopicclustergraph.getEdgeSource(e).getCharge() + "\" -> " - + this.isotopicclustergraph.getEdgeTarget(e).getStatus()) - .append("[color=\"" + e.getColor() + "\",label=\"" + Math.round(e.getScore() * 10000d) / 10000d - + "\",weight=\"" + e.getScore() + "\"];") + stringbuilder + .append("] z:" + this.isotopicclustergraph.getEdgeSource(connection).getCharge() + "\" -> " + + this.isotopicclustergraph.getEdgeTarget(connection).getStatus()) + .append("[color=\"" + connection.getColor() + "\",label=\"" + + Math.round(connection.getScore() * 10000d) / 10000d + "\",weight=\"" + + connection.getScore() + "\"];") .append(linesep); } } - sb.append("}"); + stringbuilder.append("}"); - return sb.toString(); + return stringbuilder.toString(); } - public IsotopicClusterGraph(List is) { - this.min = Double.MAX_VALUE; - is.add(new IsotopicCluster("start")); + public IsotopicClusterGraph(List isotopicset) { + this.minimum = Double.MAX_VALUE; + isotopicset.add(new IsotopicCluster("start")); - for (IsotopicCluster ic1 : is) { - for (IsotopicCluster ic2 : is) { - String color = calculateConnection(ic1, ic2); + for (IsotopicCluster isotopiccluster1 : isotopicset) { + for (IsotopicCluster isotopiccluster2 : isotopicset) { + String color = calculateConnection(isotopiccluster1, isotopiccluster2); // Start - if (color != null && ic1.getIsotopicCluster() == null && ic2.getIsotopicCluster() != null) { - connectClusters(ic1, ic2, color); + if (color != null && isotopiccluster1.getIsotopicCluster() == null + && isotopiccluster2.getIsotopicCluster() != null) { + connectClusters(isotopiccluster1, isotopiccluster2, color); } // Other - if (color != null && ic1.getIsotopicCluster() != null && ic2.getIsotopicCluster() != null) { - connectClusters(ic1, ic2, color); + if (color != null && isotopiccluster1.getIsotopicCluster() != null + && isotopiccluster2.getIsotopicCluster() != null) { + connectClusters(isotopiccluster1, isotopiccluster2, color); } } } // End - List list = new ArrayList<>(); - for (IsotopicCluster ic3 : this.isotopicclustergraph.vertexSet()) { + List isotopicclusters = new ArrayList<>(); + for (IsotopicCluster isotopiccluster1 : this.isotopicclustergraph.vertexSet()) { int edgecount = 0; - for (IsotopicCluster ic4 : this.isotopicclustergraph.vertexSet()) { - edgecount += this.isotopicclustergraph.getAllEdges(ic3, ic4).size(); + for (IsotopicCluster isotopiccluster2 : this.isotopicclustergraph.vertexSet()) { + edgecount += this.isotopicclustergraph.getAllEdges(isotopiccluster1, isotopiccluster2).size(); } if (edgecount == 0) { - list.add(ic3); + isotopicclusters.add(isotopiccluster1); } } - IsotopicCluster end = new IsotopicCluster("end"); - for (IsotopicCluster ic5 : list) { - connectClusters(ic5, end, "black"); + IsotopicCluster endcluster = new IsotopicCluster("end"); + for (IsotopicCluster isotopiccluster : isotopicclusters) { + connectClusters(isotopiccluster, endcluster, "black"); } } public void scoreIsotopicClusterGraph(double pepmass, int chargestate, double errorolerance, Peaklist peaklist, Configuration config) { - Score s = new Score(errorolerance, pepmass, chargestate, this.isotopicclustergraph, config); - - for (Connection con : this.isotopicclustergraph.edgeSet()) { - double sumscore = 0; - if (this.isotopicclustergraph.getEdgeTarget(con).getIsotopicCluster() != null) { - for (Peak x : this.isotopicclustergraph.getEdgeTarget(con).getIsotopicCluster()) { - for (Peak y : peaklist.getPeaklist()) { - if (x.getMz() > y.getMz()) { + Score score = new Score(errorolerance, pepmass, chargestate, this.isotopicclustergraph, config); + + for (Connection connection : this.isotopicclustergraph.edgeSet()) { + double scoresum = 0; + if (this.isotopicclustergraph.getEdgeTarget(connection).getIsotopicCluster() != null) { + for (Peak peakx : this.isotopicclustergraph.getEdgeTarget(connection).getIsotopicCluster()) { + for (Peak peaky : peaklist.getPeaklist()) { + if (peakx.getMz() > peaky.getMz()) { continue; } - double sres = s.calculateScore(x, y, this.isotopicclustergraph.getEdgeTarget(con), con); + double sres = score.calculateScore(peakx, peaky, + this.isotopicclustergraph.getEdgeTarget(connection), connection); - sumscore += sres; + scoresum += sres; } } - con.setScore(sumscore); - this.isotopicclustergraph.setEdgeWeight(con, sumscore); + connection.setScore(scoresum); + this.isotopicclustergraph.setEdgeWeight(connection, scoresum); } } } - private void connectClusters(IsotopicCluster ic1, IsotopicCluster ic2, String color) { - this.isotopicclustergraph.addVertex(ic1); - this.isotopicclustergraph.addVertex(ic2); + private void connectClusters(IsotopicCluster isotopiccluster1, IsotopicCluster isotopiccluster2, String color) { + this.isotopicclustergraph.addVertex(isotopiccluster1); + this.isotopicclustergraph.addVertex(isotopiccluster2); Connection connection = new Connection(color); - this.isotopicclustergraph.addEdge(ic1, ic2, connection); + this.isotopicclustergraph.addEdge(isotopiccluster1, isotopiccluster2, connection); } - private String calculateConnection(IsotopicCluster ic1, IsotopicCluster ic2) { - if (ic1.getIsotopicCluster() != null) { - if (ic1.getIsotopicCluster().get(0).getMz() < this.min) { - this.min = ic1.getIsotopicCluster().get(0).getMz(); + private String calculateConnection(IsotopicCluster isotopiccluster1, IsotopicCluster isotopiccluster2) { + if (isotopiccluster1.getIsotopicCluster() != null) { + if (isotopiccluster1.getIsotopicCluster().get(0).getMz() < this.minimum) { + this.minimum = isotopiccluster1.getIsotopicCluster().get(0).getMz(); } } - if (ic1.getStatus() == "start" && ic2.getIsotopicCluster() != null && ic1.getIsotopicCluster() == null - && ic2.getIsotopicCluster().get(0).getMz() == this.min) { + if (isotopiccluster1.getStatus() == "start" && isotopiccluster2.getIsotopicCluster() != null + && isotopiccluster1.getIsotopicCluster() == null + && isotopiccluster2.getIsotopicCluster().get(0).getMz() == this.minimum) { return "black"; } - if (ic1.getIsotopicCluster() == null || ic2.getIsotopicCluster() == null) { + if (isotopiccluster1.getIsotopicCluster() == null || isotopiccluster2.getIsotopicCluster() == null) { return null; } - if (ic1.getIsotopicCluster().get(ic1.getIsotopicCluster().size() - 1).getMz() < ic2.getIsotopicCluster().get(0) - .getMz()) { + if (isotopiccluster1.getIsotopicCluster().get(isotopiccluster1.getIsotopicCluster().size() - 1) + .getMz() < isotopiccluster2.getIsotopicCluster().get(0).getMz()) { return "black"; } - if (ic1.getIsotopicCluster().get(0).getMz() < ic2.getIsotopicCluster().get(0).getMz()) { - if (ic1.getIsotopicCluster().size() == 2) { - if (ic1.getIsotopicCluster().get(1).getMz() == ic2.getIsotopicCluster().get(0).getMz()) { + if (isotopiccluster1.getIsotopicCluster().get(0).getMz() < isotopiccluster2.getIsotopicCluster().get(0) + .getMz()) { + if (isotopiccluster1.getIsotopicCluster().size() == 2) { + if (isotopiccluster1.getIsotopicCluster().get(1).getMz() == isotopiccluster2.getIsotopicCluster().get(0) + .getMz()) { return "red"; } - } else if (ic1.getIsotopicCluster().size() == 3) { - if (ic1.getIsotopicCluster().get(1).getMz() == ic2.getIsotopicCluster().get(0).getMz() - || ic1.getIsotopicCluster().get(2).getMz() == ic2.getIsotopicCluster().get(0).getMz()) { + } else if (isotopiccluster1.getIsotopicCluster().size() == 3) { + if (isotopiccluster1.getIsotopicCluster().get(1).getMz() == isotopiccluster2.getIsotopicCluster().get(0) + .getMz() + || isotopiccluster1.getIsotopicCluster().get(2).getMz() == isotopiccluster2.getIsotopicCluster() + .get(0).getMz()) { return "red"; } - } else if (ic1.getIsotopicCluster().size() == 3) { - if (ic1.getIsotopicCluster().get(1).getMz() == ic2.getIsotopicCluster().get(0).getMz() - && ic1.getIsotopicCluster().get(2).getMz() == ic2.getIsotopicCluster().get(1).getMz()) { + } else if (isotopiccluster1.getIsotopicCluster().size() == 3) { + if (isotopiccluster1.getIsotopicCluster().get(1).getMz() == isotopiccluster2.getIsotopicCluster().get(0) + .getMz() + && isotopiccluster1.getIsotopicCluster().get(2).getMz() == isotopiccluster2.getIsotopicCluster() + .get(1).getMz()) { return "red"; } } diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicMassSpectrum.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicMassSpectrum.java index d8655e5..5122e28 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicMassSpectrum.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicMassSpectrum.java @@ -17,11 +17,12 @@ public List getIsotopicMassSpectrum() { return isotopicmassspectrum; } - public IsotopicMassSpectrum(MassSpectrum massspectrum, double delta, Configuration config) { - this(massspectrum, new Peaklist(massspectrum), delta, config); + public IsotopicMassSpectrum(MassSpectrum massspectrum, double delta, Configuration config, Deisotoper deisotoper) { + this(massspectrum, new Peaklist(massspectrum), delta, config, deisotoper); } - public IsotopicMassSpectrum(MassSpectrum massspectrum, Peaklist peaklist, double delta, Configuration config) { + public IsotopicMassSpectrum(MassSpectrum massspectrum, Peaklist peaklist, double delta, Configuration config, + Deisotoper deisotoper) { int id = 0; for (int i = 0; i < peaklist.getPeaklist().size(); i++) { List isotopicset = new ArrayList<>(); @@ -59,5 +60,31 @@ public IsotopicMassSpectrum(MassSpectrum massspectrum, Peaklist peaklist, double } } } + + saveAnnotatedSpectrum(deisotoper, this); + } + + private void saveAnnotatedSpectrum(Deisotoper deisotoper, IsotopicMassSpectrum isotopicmassspectrum) { + deisotoper.setAnnotatedSpectrum(null); + + StringBuilder stringbuilder = new StringBuilder(); + String linesep = System.getProperty("line.separator"); + + stringbuilder.append("IsotopicSet,IsotopicCluster,Peak,Charge,mZ,Intensity").append(linesep); + + for (IsotopicSet isotopicset : isotopicmassspectrum.getIsotopicMassSpectrum()) { + for (IsotopicCluster isotopiccluster : isotopicset.getIsotopicSet()) { + if (isotopiccluster.getIsotopicCluster() != null) { + for (Peak peak : isotopiccluster.getIsotopicCluster()) { + stringbuilder.append(isotopicset.getSetID()).append(",").append(isotopiccluster.getClusterID()) + .append(",").append(peak.getPeakID()).append(",").append(isotopiccluster.getCharge()) + .append(",").append(peak.getMz()).append(",").append(peak.getIntensity()) + .append(linesep); + } + } + } + } + + deisotoper.setAnnotatedSpectrum(stringbuilder.toString()); } } diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicSet.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicSet.java index 3e1f6fa..6a37ca8 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicSet.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/IsotopicSet.java @@ -18,7 +18,7 @@ public class IsotopicSet { private List isotopicset = new ArrayList<>(); - private IsotopicClusterGraph icg; + private IsotopicClusterGraph isotopicclustergraph; private GraphPath bestpath; private int setID; @@ -30,26 +30,25 @@ public List getIsotopicSet() { return isotopicset; } - // TODO (LS) : Make private - public IsotopicClusterGraph getIcg() { - return icg; + public IsotopicClusterGraph getIsotopicClusterGraph() { + return isotopicclustergraph; } - // TODO (LS) : This should return only the clusters in the best path. - public GraphPath getBestPath() { - return bestpath; + public List getBestPath() { + return bestpath.getVertexList(); } - private void setBestPath(MassSpectrum ms, List is, Configuration config) { - IsotopicClusterGraph icg = new IsotopicClusterGraph(is); + private void setBestPath(MassSpectrum massspectrum, List isotopicclusters, Configuration config) { + IsotopicClusterGraph isotopicclustergraph = new IsotopicClusterGraph(isotopicclusters); - icg.scoreIsotopicClusterGraph(ms.getPeptideMass(), ms.getChargeState(), config.getErrortolerance(), - new Peaklist(ms.getMz(), ms.getIntensity()), config); + isotopicclustergraph.scoreIsotopicClusterGraph(massspectrum.getPeptideMass(), massspectrum.getChargeState(), + config.getErrortolerance(), new Peaklist(massspectrum.getMz(), massspectrum.getIntensity()), config); - GraphPath bp = icg.bestPath(getStart(icg), getEnd(icg)); + GraphPath bestpath = isotopicclustergraph.bestPath(getStart(isotopicclustergraph), + getEnd(isotopicclustergraph)); - this.icg = icg; - this.bestpath = bp; + this.isotopicclustergraph = isotopicclustergraph; + this.bestpath = bestpath; } public IsotopicSet(MassSpectrum massspectrum, List isotopicset, double delta, int setid, @@ -60,32 +59,32 @@ public IsotopicSet(MassSpectrum massspectrum, List isotopicset, double del e.printStackTrace(); } - List is = new ArrayList<>(); + List isotopicclusters = new ArrayList<>(); - is = collectClusterForEachCharge(is, isotopicset, 3, delta, config); + isotopicclusters = collectClusterForEachCharge(isotopicclusters, isotopicset, 3, delta, config); - is = collectClusterForEachCharge(is, isotopicset, 2, delta, config); + isotopicclusters = collectClusterForEachCharge(isotopicclusters, isotopicset, 2, delta, config); - is = collectClusterForEachCharge(is, isotopicset, 1, delta, config); + isotopicclusters = collectClusterForEachCharge(isotopicclusters, isotopicset, 1, delta, config); - is = removeMultipleIsotopicCluster(is); + isotopicclusters = removeMultipleIsotopicCluster(isotopicclusters); - is = sortIsotopicSet(is); + isotopicclusters = sortIsotopicSet(isotopicclusters); int clusterid = 0; - for (IsotopicCluster cluster : is) { + for (IsotopicCluster cluster : isotopicclusters) { cluster.setClusterID(clusterid); clusterid++; } - - setBestPath(massspectrum, is, config); - this.isotopicset = is; + setBestPath(massspectrum, isotopicclusters, config); + + this.isotopicset = isotopicclusters; this.setID = setid; } - private List collectClusterForEachCharge(List is, List isotopicset, - int charge, double delta, Configuration config) { + private List collectClusterForEachCharge(List isotopicclusters, + List isotopicset, int charge, double delta, Configuration config) { for (Peak a : isotopicset) { for (Peak b : isotopicset) { double distanceab = b.getMz() - a.getMz(); @@ -109,29 +108,29 @@ private List collectClusterForEachCharge(List if (ic.size() == 2 || ic.size() == 3) { IsotopicCluster cluster = new IsotopicCluster(ic, charge, config); - is.add(cluster); + isotopicclusters.add(cluster); } } } } - return is; + return isotopicclusters; } - private static List sortIsotopicSet(List list) { - Collections.sort(list, new Comparator() { + private static List sortIsotopicSet(List isotopicclusters) { + Collections.sort(isotopicclusters, new Comparator() { @Override - public int compare(IsotopicCluster o1, IsotopicCluster o2) { - int result = Double.compare(o1.getIsotopicCluster().get(0).getMz(), - o2.getIsotopicCluster().get(0).getMz()); + public int compare(IsotopicCluster cluster1, IsotopicCluster cluster2) { + int result = Double.compare(cluster1.getIsotopicCluster().get(0).getMz(), + cluster2.getIsotopicCluster().get(0).getMz()); if (result == 0) { - result = Double.compare(o1.getIsotopicCluster().get(1).getMz(), - o2.getIsotopicCluster().get(1).getMz()); + result = Double.compare(cluster1.getIsotopicCluster().get(1).getMz(), + cluster2.getIsotopicCluster().get(1).getMz()); if (result == 0) { - if (o1.getIsotopicCluster().size() == 3 && o2.getIsotopicCluster().size() == 3) { - result = Double.compare(o1.getIsotopicCluster().get(2).getMz(), - o2.getIsotopicCluster().get(2).getMz()); + if (cluster1.getIsotopicCluster().size() == 3 && cluster2.getIsotopicCluster().size() == 3) { + result = Double.compare(cluster1.getIsotopicCluster().get(2).getMz(), + cluster2.getIsotopicCluster().get(2).getMz()); return result; } } @@ -141,22 +140,40 @@ public int compare(IsotopicCluster o1, IsotopicCluster o2) { } }); - return list; + return isotopicclusters; } - private static List removeMultipleIsotopicCluster(List list) { + private static List removeMultipleIsotopicCluster(List isotopicclusters) { List result = new ArrayList<>(); - Set> titles = new HashSet<>(); + Set> set = new HashSet<>(); - for (IsotopicCluster item : list) { - if (titles.add(item.getIsotopicCluster())) { - result.add(item); + for (IsotopicCluster cluster : isotopicclusters) { + if (set.add(cluster.getIsotopicCluster())) { + result.add(cluster); } } return result; } + private IsotopicCluster getStart(IsotopicClusterGraph isotopicclustergraph) { + for (IsotopicCluster cluster : isotopicclustergraph.getIsotopicclustergraph().vertexSet()) { + if (cluster.getIsotopicCluster() == null && cluster.getStatus() == "start") { + return cluster; + } + } + return null; + } + + private IsotopicCluster getEnd(IsotopicClusterGraph isotopicclustergraph) { + for (IsotopicCluster cluster : isotopicclustergraph.getIsotopicclustergraph().vertexSet()) { + if (cluster.getIsotopicCluster() == null && cluster.getStatus() == "end") { + return cluster; + } + } + return null; + } + private static void rangeCheck(List peaks, Configuration config) throws Exception { for (int i = 0; i < peaks.size() - 1; i++) { double distance = peaks.get(i + 1).getMz() - peaks.get(i).getMz(); @@ -174,22 +191,4 @@ private static void rangeCheck(List peaks, Configuration config) throws Ex } } } - - private IsotopicCluster getStart(IsotopicClusterGraph icg) { - for (IsotopicCluster e : icg.getIsotopicclustergraph().vertexSet()) { - if (e.getIsotopicCluster() == null && e.getStatus() == "start") { - return e; - } - } - return null; - } - - private IsotopicCluster getEnd(IsotopicClusterGraph icg) { - for (IsotopicCluster e : icg.getIsotopicclustergraph().vertexSet()) { - if (e.getIsotopicCluster() == null && e.getStatus() == "end") { - return e; - } - } - return null; - } } \ No newline at end of file diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Peaklist.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Peaklist.java index 0d36d25..d989912 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Peaklist.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Peaklist.java @@ -17,11 +17,11 @@ public List getPeaklist() { return peaklist; } - public Peaklist(MassSpectrum ms) { + public Peaklist(MassSpectrum massspectrum) { List plist = new ArrayList<>(); - for (int i = 0; i < ms.getMz().size() || i < ms.getIntensity().size(); i++) { - plist.add(new Peak(ms.getMz().get(i), ms.getIntensity().get(i), i)); + for (int i = 0; i < massspectrum.getMz().size() || i < massspectrum.getIntensity().size(); i++) { + plist.add(new Peak(massspectrum.getMz().get(i), massspectrum.getIntensity().get(i), i)); } this.peaklist = plist; diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Score.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Score.java index 67453d3..7a041bd 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Score.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Score.java @@ -14,22 +14,22 @@ public class Score { private DefaultDirectedWeightedGraph icg; private Configuration config; - public Score(double error, double mspepmass, double mscharge, + public Score(double error, double pepmass, double charge, DefaultDirectedWeightedGraph isotopicclustergraph, Configuration config) { this.errorvalue = error; - this.pepmassvalue = mspepmass; - this.chargevalue = mscharge; + this.pepmassvalue = pepmass; + this.chargevalue = charge; this.icg = isotopicclustergraph; this.config = config; } - public double calculateScore(Peak x, Peak y, IsotopicCluster icx, Connection con) { - return this.config.getFM1() * firstScoringFeature(x, y, this.errorvalue, this.config) - + this.config.getFM2() * secondScoringFeature(x, y, this.errorvalue, this.pepmassvalue, - this.chargevalue, icx, this.config) - + this.config.getFM3() * thirdScoringFeature(x, y, this.errorvalue, this.config) - + this.config.getFM4() * fourthScoringFeature(x, y, this.errorvalue, this.config) - + this.config.getFM5() * Score5.fifthScoringFeature(con, this.icg, this.config); + public double calculateScore(Peak peakx, Peak peaky, IsotopicCluster isotopicclusterofx, Connection connection) { + return this.config.getFM1() * firstScoringFeature(peakx, peaky, this.errorvalue, this.config) + + this.config.getFM2() * secondScoringFeature(peakx, peaky, this.errorvalue, this.pepmassvalue, + this.chargevalue, isotopicclusterofx, this.config) + + this.config.getFM3() * thirdScoringFeature(peakx, peaky, this.errorvalue, this.config) + + this.config.getFM4() * fourthScoringFeature(peakx, peaky, this.errorvalue, this.config) + + this.config.getFM5() * Score5.fifthScoringFeature(connection, this.icg, this.config); } protected static double diff1(Peak x, Peak y, Configuration config) { diff --git a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Score5.java b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Score5.java index 8032dce..cec5be9 100644 --- a/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Score5.java +++ b/java/deisotoper/src/main/java/ch/fgcz/proteomics/fbdm/Score5.java @@ -9,37 +9,37 @@ public class Score5 { // NOT FINISHED YET - public static int fifthScoringFeature(Connection con, + public static int fifthScoringFeature(Connection connection, DefaultDirectedWeightedGraph isotopicclustergraph, Configuration config) { int F5 = 0; double threshold = 0.3; int i = 0; - for (Peak p : isotopicclustergraph.getEdgeTarget(con).getIsotopicCluster()) { + for (Peak p : isotopicclustergraph.getEdgeTarget(connection).getIsotopicCluster()) { double T_MIN = (p.getMz() / config.getASP_MASS()) * p.getIntensity(); double T_MEAN = (p.getMz() / config.getAVE_UPDATED_MASS()) * p.getIntensity(); double T_MEAN_OVERLAP = 0; - if (isotopicclustergraph.getEdgeSource(con).getIsotopicCluster() != null) { - if (i < isotopicclustergraph.getEdgeSource(con).getIsotopicCluster().size()) { - T_MEAN_OVERLAP = (isotopicclustergraph.getEdgeSource(con).getIsotopicCluster().get(i).getMz() + if (isotopicclustergraph.getEdgeSource(connection).getIsotopicCluster() != null) { + if (i < isotopicclustergraph.getEdgeSource(connection).getIsotopicCluster().size()) { + T_MEAN_OVERLAP = (isotopicclustergraph.getEdgeSource(connection).getIsotopicCluster().get(i).getMz() / config.getAVE_UPDATED_MASS()) * p.getIntensity(); } else { - T_MEAN_OVERLAP = (isotopicclustergraph.getEdgeSource(con).getIsotopicCluster() - .get(isotopicclustergraph.getEdgeSource(con).getIsotopicCluster().size() - 1).getMz() + T_MEAN_OVERLAP = (isotopicclustergraph.getEdgeSource(connection).getIsotopicCluster() + .get(isotopicclustergraph.getEdgeSource(connection).getIsotopicCluster().size() - 1).getMz() / config.getAVE_UPDATED_MASS()) * p.getIntensity(); } } double T_MAX = (p.getMz() / config.getPHE_MASS()) * p.getIntensity(); - if (con.getColor() == "black") { + if (connection.getColor() == "black") { if (Math.min(Math.abs(p.getIntensity() - T_MIN), Math.abs(p.getIntensity() - T_MAX)) / T_MEAN <= threshold) { F5++; } } - if (con.getColor() == "red") { + if (connection.getColor() == "red") { if (Math.min(Math.abs((p.getIntensity() - T_MEAN_OVERLAP) - T_MIN), Math.abs((p.getIntensity() - T_MEAN_OVERLAP) - T_MAX)) / T_MEAN <= threshold) { F5++; diff --git a/java/deisotoper/src/test/java/ch/fgcz/proteomics/fbdm/IsotopicTest.java b/java/deisotoper/src/test/java/ch/fgcz/proteomics/fbdm/IsotopicTest.java index 0fe8045..ebef1f0 100644 --- a/java/deisotoper/src/test/java/ch/fgcz/proteomics/fbdm/IsotopicTest.java +++ b/java/deisotoper/src/test/java/ch/fgcz/proteomics/fbdm/IsotopicTest.java @@ -93,44 +93,44 @@ private void assertPeaklistEquals(List list, List list2) { // public void testDeisotope() { // String typ = "MS2 Spectrum"; // String searchengine = "mascot"; -// double[] mz = { 110.0715485, 110.1648788, 112.0395432, 113.0712204, -// 114.0746384, 115.05056, 115.9784622, 120.080986, 120.0833893, 121.0843735, -// 125.7498245, 129.0659332, 129.1023102, -// 130.0863342, 130.1057281, 131.0815735, 132.0849609, 132.5098419, 137.0346222, -// 141.0658417, 143.0816193, 145.0608368, 147.1128235, 149.0233917, 150.0266876, -// 153.0657654, 157.0970917, -// 159.076416, 160.0798035, 162.0875397, 162.0912323, 167.0816345, 170.092392, -// 171.0762177, 172.8989868, 175.118927, 180.0767212, 185.0920105, 189.1023407, -// 198.0873413, 199.0907135, -// 204.0980682, 205.0570374, 207.1127777, 208.0717316, 210.0866547, 210.7322388, -// 211.5193329, 212.10289, 214.0822296, 216.0977783, 223.0636444, 224.1031799, -// 225.0603638, 226.0820923, -// 227.0399933, 227.1023407, 228.098175, 230.1135101, 231.1125488, 231.1492462, -// 232.0926361, 232.2126312, 233.1646729, 235.1072845, 240.09758, 241.129364, -// 242.1128387, 246.1234741, -// 249.098175, 253.0928345, 254.1314087, 254.6329193, 255.1085358, 258.1084595, -// 259.1398315, 263.1368713, 267.1086426, 268.1119995, 269.1243591, 271.1038513, -// 273.1199646, 274.1184998, -// 276.1701965, 277.0926819, 277.1541138, 278.4438171, 279.108429, 285.1191101, -// 287.1348877, 289.650177, 292.1772461, 294.1808777, 295.1038513, 295.184082, -// 296.1346436, 297.1190491, -// 299.0617065, 300.133606, 301.0583801, 303.1295166, 310.4591064, 314.1459961, -// 315.129303, 318.1446228, 318.1605225, 324.1297607, 328.1278992, 331.8494568, -// 332.1560364, 333.1555786, -// 334.114502, 338.1456299, 342.1403198, 343.1411133, 346.176239, 351.1661377, -// 356.1558228, 357.1579285, 357.6632385, 358.1647949, 360.1513672, 360.6679077, -// 361.1502075, 363.2023926, -// 366.6683655, 368.6846924, 375.1660156, 375.2023926, 379.1607361, 381.2128296, -// 382.2158813, 387.1657104, 388.1895447, 390.9455261, 395.1658325, 397.1503906, -// 397.1950684, 397.6967163, -// 400.1613159, 403.135437, 403.1973877, 411.1614075, 418.1715698, 420.2235107, -// 421.1462402, 421.2265015, 426.1759949, 438.2343445, 439.2384644, 443.2040405, -// 444.1874084, 454.1725464, -// 461.2140198, 462.1977844, 471.1980896, 472.2180786, 479.2248535, 482.1990967, -// 489.2085571, 490.2118835, 490.2296448, 495.2563477, 507.2199402, 507.2555847, -// 508.2598572, 525.2663574, -// 526.2697754, 577.2515259, 578.2937012, 584.8656006, 596.3037109, 597.3069458, -// 617.3034668, 618.2872925, 635.3146362, 636.3175049, 653.3252563, 654.3284302 + // double[] mz = { 110.0715485, 110.1648788, 112.0395432, 113.0712204, + // 114.0746384, 115.05056, 115.9784622, 120.080986, 120.0833893, 121.0843735, + // 125.7498245, 129.0659332, 129.1023102, + // 130.0863342, 130.1057281, 131.0815735, 132.0849609, 132.5098419, 137.0346222, + // 141.0658417, 143.0816193, 145.0608368, 147.1128235, 149.0233917, 150.0266876, + // 153.0657654, 157.0970917, + // 159.076416, 160.0798035, 162.0875397, 162.0912323, 167.0816345, 170.092392, + // 171.0762177, 172.8989868, 175.118927, 180.0767212, 185.0920105, 189.1023407, + // 198.0873413, 199.0907135, + // 204.0980682, 205.0570374, 207.1127777, 208.0717316, 210.0866547, 210.7322388, + // 211.5193329, 212.10289, 214.0822296, 216.0977783, 223.0636444, 224.1031799, + // 225.0603638, 226.0820923, + // 227.0399933, 227.1023407, 228.098175, 230.1135101, 231.1125488, 231.1492462, + // 232.0926361, 232.2126312, 233.1646729, 235.1072845, 240.09758, 241.129364, + // 242.1128387, 246.1234741, + // 249.098175, 253.0928345, 254.1314087, 254.6329193, 255.1085358, 258.1084595, + // 259.1398315, 263.1368713, 267.1086426, 268.1119995, 269.1243591, 271.1038513, + // 273.1199646, 274.1184998, + // 276.1701965, 277.0926819, 277.1541138, 278.4438171, 279.108429, 285.1191101, + // 287.1348877, 289.650177, 292.1772461, 294.1808777, 295.1038513, 295.184082, + // 296.1346436, 297.1190491, + // 299.0617065, 300.133606, 301.0583801, 303.1295166, 310.4591064, 314.1459961, + // 315.129303, 318.1446228, 318.1605225, 324.1297607, 328.1278992, 331.8494568, + // 332.1560364, 333.1555786, + // 334.114502, 338.1456299, 342.1403198, 343.1411133, 346.176239, 351.1661377, + // 356.1558228, 357.1579285, 357.6632385, 358.1647949, 360.1513672, 360.6679077, + // 361.1502075, 363.2023926, + // 366.6683655, 368.6846924, 375.1660156, 375.2023926, 379.1607361, 381.2128296, + // 382.2158813, 387.1657104, 388.1895447, 390.9455261, 395.1658325, 397.1503906, + // 397.1950684, 397.6967163, + // 400.1613159, 403.135437, 403.1973877, 411.1614075, 418.1715698, 420.2235107, + // 421.1462402, 421.2265015, 426.1759949, 438.2343445, 439.2384644, 443.2040405, + // 444.1874084, 454.1725464, + // 461.2140198, 462.1977844, 471.1980896, 472.2180786, 479.2248535, 482.1990967, + // 489.2085571, 490.2118835, 490.2296448, 495.2563477, 507.2199402, 507.2555847, + // 508.2598572, 525.2663574, + // 526.2697754, 577.2515259, 578.2937012, 584.8656006, 596.3037109, 597.3069458, + // 617.3034668, 618.2872925, 635.3146362, 636.3175049, 653.3252563, 654.3284302 // }; // double[] intensity = { 6250.6640625, 563.5891113281, 787.7743530273, // 42913.109375, 927.4467773438, 2023.1707763672, 529.0408325195, 25228.6796875, @@ -929,35 +929,37 @@ private void assertPeaklistEquals(List list, List list2) { // (int) (Score.timescoref5 / time * 100) + "%)"); // } - @Test - public void testIsotopicMassSpectrum() { - String s = "TesterinoData.RData"; - - String typ = "MS2 Spectrum"; - String searchengine = "mascot"; - double[] mz = { 1, 1.5, 2, 3, 3.5, 4.5, 4.83, 5.15, 5.5, 6, 6.5, 7, 8, 9, 10 }; - double[] intensity = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - double peptidmass = 309.22; - double rt = 38383.34; - int chargestate = 2; - int id = 123; - - MassSpectrometryMeasurement MSM = new MassSpectrometryMeasurement(s); - MSM.addMS(typ, searchengine, mz, intensity, peptidmass, rt, chargestate, id); - - IsotopicMassSpectrum test = new IsotopicMassSpectrum(MSM.getMSlist().get(0), 0.01, new Configuration()); - - for (IsotopicSet is : test.getIsotopicMassSpectrum()) { - System.out.println("(((" + is.getSetID() + ")))"); - for (IsotopicCluster ic : is.getIsotopicSet()) { - System.out.print("((" + ic.getClusterID() + ")) (" + ic.getCharge() + ") "); - for (Peak p : ic.getIsotopicCluster()) { - System.out.print(p.getMz() + " "); - } - - System.out.println(); - } - System.out.println(); - } - } + // @Test + // public void testIsotopicMassSpectrum() { + // String s = "TesterinoData.RData"; + // + // String typ = "MS2 Spectrum"; + // String searchengine = "mascot"; + // double[] mz = { 1, 1.5, 2, 3, 3.5, 4.5, 4.83, 5.15, 5.5, 6, 6.5, 7, 8, 9, 10 + // }; + // double[] intensity = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + // double peptidmass = 309.22; + // double rt = 38383.34; + // int chargestate = 2; + // int id = 123; + // + // MassSpectrometryMeasurement MSM = new MassSpectrometryMeasurement(s); + // MSM.addMS(typ, searchengine, mz, intensity, peptidmass, rt, chargestate, id); + // + // IsotopicMassSpectrum test = new IsotopicMassSpectrum(MSM.getMSlist().get(0), + // 0.01, new Configuration()); + // + // for (IsotopicSet is : test.getIsotopicMassSpectrum()) { + // System.out.println("(((" + is.getSetID() + ")))"); + // for (IsotopicCluster ic : is.getIsotopicSet()) { + // System.out.print("((" + ic.getClusterID() + ")) (" + ic.getCharge() + ") "); + // for (Peak p : ic.getIsotopicCluster()) { + // System.out.print(p.getMz() + " "); + // } + // + // System.out.println(); + // } + // System.out.println(); + // } + // } }