package com.compomics.util.experiment.massspectrometry; import com.compomics.util.experiment.io.massspectrometry.MgfIndex; import com.compomics.util.experiment.io.massspectrometry.MgfReader; import com.compomics.util.experiment.massspectrometry.indexes.PrecursorMap; import com.compomics.util.waiting.WaitingHandler; import com.compomics.util.io.SerializationUtils; import java.io.*; import java.net.URLDecoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.concurrent.LinkedBlockingDeque; import uk.ac.ebi.jmzml.model.mzml.BinaryDataArray; import uk.ac.ebi.jmzml.model.mzml.CVParam; import uk.ac.ebi.jmzml.model.mzml.PrecursorList; import uk.ac.ebi.jmzml.model.mzml.ScanList; import uk.ac.ebi.jmzml.model.mzml.SelectedIonList; import uk.ac.ebi.jmzml.xml.io.MzMLUnmarshaller; import uk.ac.ebi.jmzml.xml.io.MzMLUnmarshallerException; import uk.ac.ebi.pride.tools.braf.BufferedRandomAccessFile; /** * This factory will provide the spectra when needed. * * @author Marc Vaudel * @author Harald Barsnes */ public class SpectrumFactory { /** * The instance of the factory. */ private static SpectrumFactory instance = null; /** * Map of already loaded spectra. */ private HashMap<String, HashMap<String, Spectrum>> currentSpectrumMap = new HashMap<String, HashMap<String, Spectrum>>(); /** * Map of already loaded precursors. */ private HashMap<String, HashMap<String, Precursor>> loadedPrecursorsMap = new HashMap<String, HashMap<String, Precursor>>(); /** * Maximal number of spectra in cache. By default 1000000, which corresponds to approx. 110MB. */ private static int nSpectraCache = 1000000; /** * List of the loaded spectra. */ private LinkedBlockingDeque<String> loadedSpectra = new LinkedBlockingDeque<String>(); /** * Map to the different files. */ private HashMap<String, File> filesMap = new HashMap<String, File>(); /** * Map of the random access files of the loaded mgf files (filename > * random access file). */ private HashMap<String, BufferedRandomAccessFile> mgfRandomAccessFilesMap = new HashMap<String, BufferedRandomAccessFile>(); /** * Map of the mgf indexes (fileName > mgf index). */ private HashMap<String, MgfIndex> mgfIndexesMap = new HashMap<String, MgfIndex>(); /** * Map of the mzML unmarshallers (fileName > unmarshaller). */ private HashMap<String, MzMLUnmarshaller> mzMLUnmarshallers = new HashMap<String, MzMLUnmarshaller>(); /** * Map of the spectrum file mapped according to the name used by the search * engine. */ private HashMap<String, File> idToSpectrumName = new HashMap<String, File>(); /** * The time out in milliseconds when querying the file. */ public final static long timeOut = 10000; /** * Constructor. */ private SpectrumFactory() { } /** * Static method returning the instance of the factory. * * @return the instance of the factory */ public static SpectrumFactory getInstance() { if (instance == null) { instance = new SpectrumFactory(); } return instance; } /** * Static method returning the instance of the factory with a new cache * size. * * @param nCache the cache size * @return the instance of the factory with a new cache size */ public static SpectrumFactory getInstance(int nCache) { if (instance == null) { instance = new SpectrumFactory(); } instance.setCacheSize(nCache); return instance; } /** * Clears the factory getInstance() needs to be called afterwards. */ public void clearFactory() { currentSpectrumMap.clear(); loadedPrecursorsMap.clear(); loadedSpectra.clear(); filesMap.clear(); mgfRandomAccessFilesMap.clear(); mgfIndexesMap.clear(); mzMLUnmarshallers.clear(); idToSpectrumName.clear(); } /** * Empties the cache. */ public void emptyCache() { currentSpectrumMap.clear(); loadedPrecursorsMap.clear(); loadedSpectra.clear(); } /** * Sets the spectrum cache size. * * @param nCache the new cache size */ public void setCacheSize(int nCache) { SpectrumFactory.nSpectraCache = nCache; } /** * Returns the spectrum cache size. * * @return the cache size */ public int getCacheSize() { return nSpectraCache; } /** * Add spectra to the factory. * * @param spectrumFile The spectrum file, can be mgf or mzML * * @throws FileNotFoundException Exception thrown whenever the file was not * found * @throws IOException Exception thrown whenever an error occurred while * reading the file * @throws ClassNotFoundException Exception thrown whenever an error * occurred while deserializing the index .cui file. * */ public void addSpectra(File spectrumFile) throws FileNotFoundException, IOException, ClassNotFoundException { addSpectra(spectrumFile, null); } /** * Add spectra to the factory. * * @param spectrumFile The spectrum file, can be mgf or mzML * @param waitingHandler the waiting handler * * @throws FileNotFoundException Exception thrown whenever the file was not * found * @throws IOException Exception thrown whenever an error occurred while * reading the file * @throws IllegalArgumentException Exception thrown if an unknown format * was detected. */ public void addSpectra(File spectrumFile, WaitingHandler waitingHandler) throws FileNotFoundException, IOException, IllegalArgumentException { String fileName = spectrumFile.getName(); filesMap.put(fileName, spectrumFile); if (fileName.toLowerCase().endsWith(".mgf")) { File indexFile = new File(spectrumFile.getParent(), getIndexName(fileName)); MgfIndex mgfIndex = null; if (indexFile.exists()) { try { MgfIndex tempIndex = getIndex(indexFile); Long indexLastModified = tempIndex.getLastModified(); if (indexLastModified != null) { long fileLastModified = spectrumFile.lastModified(); if (indexLastModified == fileLastModified) { mgfIndex = tempIndex; } else { System.err.println("Reindexing: " + fileName + ". (changes in the file detected)"); } } } catch (Exception e) { System.err.println("Reindexing: " + fileName + ". (Reason: " + e.getLocalizedMessage() + ")"); } } if (mgfIndex == null) { mgfIndex = MgfReader.getIndexMap(spectrumFile, waitingHandler); if (waitingHandler != null && waitingHandler.isRunCanceled()) { return; // return without saving the partial index } writeIndex(mgfIndex, spectrumFile.getParentFile()); } if (mgfIndex == null) { throw new IllegalArgumentException("An error occurred while indexing " + spectrumFile.getAbsolutePath()); } mgfRandomAccessFilesMap.put(fileName, new BufferedRandomAccessFile(spectrumFile, "r", 1024 * 100)); mgfIndexesMap.put(fileName, mgfIndex); } else if (fileName.toLowerCase().endsWith(".mzml")) { MzMLUnmarshaller mzMLUnmarshaller = new MzMLUnmarshaller(spectrumFile); mzMLUnmarshallers.put(fileName, mzMLUnmarshaller); } else { throw new IllegalArgumentException("Spectrum file format not supported."); } } /** * Returns the name of an index file based on the given spectrum file name. * * @param spectrumFileName the name of the spectrum file * * @return the corresponding name of the index file */ public static String getIndexName(String spectrumFileName) { return spectrumFileName + ".cui"; } /** * Returns the precursor of the desired spectrum. The value will be saved in * cache. * * @param fileName the name of the spectrum file * @param spectrumTitle the title of the spectrum * * @return the corresponding precursor * * @throws IOException exception thrown whenever the file was not parsed * correctly * @throws MzMLUnmarshallerException exception thrown whenever the file was * not parsed correctly */ public Precursor getPrecursor(String fileName, String spectrumTitle) throws IOException, MzMLUnmarshallerException { return getPrecursor(fileName, spectrumTitle, true); } /** * Returns the precursor of the desired spectrum. * * @param fileName the name of the spectrum file * @param spectrumTitle the title of the spectrum * @param save if true the precursor will be saved in cache * * @return the corresponding precursor * * @throws IOException exception thrown whenever the file was not parsed * correctly * @throws MzMLUnmarshallerException exception thrown whenever the file was * not parsed correctly */ public Precursor getPrecursor(String fileName, String spectrumTitle, boolean save) throws IOException, MzMLUnmarshallerException { HashMap<String, Spectrum> fileSpectrumMap = currentSpectrumMap.get(fileName); if (fileSpectrumMap != null) { Spectrum spectrum = fileSpectrumMap.get(spectrumTitle); if (spectrum != null) { return ((MSnSpectrum) spectrum).getPrecursor(); } } HashMap<String, Precursor> filePrecursorMap = loadedPrecursorsMap.get(fileName); if (filePrecursorMap != null) { Precursor currentPrecursor = filePrecursorMap.get(spectrumTitle); if (currentPrecursor != null) { return currentPrecursor; } } return getPrecursor(fileName, spectrumTitle, save, 1); } /** * Returns the precursor of the desired spectrum. The value will be saved in * cache. * * @param spectrumKey the key of the spectrum * @return the corresponding precursor * @throws IOException exception thrown whenever the file was not parsed * correctly * @throws MzMLUnmarshallerException exception thrown whenever the file was * not parsed correctly */ public Precursor getPrecursor(String spectrumKey) throws IOException, MzMLUnmarshallerException { return getPrecursor(spectrumKey, true); } /** * Returns the precursor mz of the desired spectrum. The value will be saved * in cache. * * @param spectrumKey the key of the spectrum * @return the corresponding precursor mz * * @throws IOException exception thrown whenever the file was not parsed * correctly * @throws MzMLUnmarshallerException exception thrown whenever the file was * not parsed correctly */ public double getPrecursorMz(String spectrumKey) throws IOException, MzMLUnmarshallerException { // get the spectrum title and file name String spectrumTitle = Spectrum.getSpectrumTitle(spectrumKey); String spectrumFileName = Spectrum.getSpectrumFile(spectrumKey); // a special fix for mgf files with strange titles... spectrumTitle = fixMgfTitle(spectrumTitle, spectrumFileName); // see if the have the precursor mz in the mgf index int spectrumIndex = mgfIndexesMap.get(spectrumFileName).getSpectrumIndex(spectrumTitle); Double precursorMz = mgfIndexesMap.get(spectrumFileName).getPrecursorMz(spectrumIndex); if (precursorMz != null) { return precursorMz; } else { Precursor precursor = getPrecursor(spectrumKey); precursorMz = precursor.getMz(); return precursorMz; } } /** * Returns the maximum m/z for the desired file. * * @param fileName the file of interest * @return the max m/z */ public Double getMaxMz(String fileName) { return mgfIndexesMap.get(fileName).getMaxMz(); } /** * Returns the maximum m/z for the whole project. * * @return the max m/z */ public Double getMaxMz() { double maxMz = 0; for (MgfIndex mgfIndex : mgfIndexesMap.values()) { if (maxMz < mgfIndex.getMaxMz()) { maxMz = mgfIndex.getMaxMz(); } } return maxMz; } /** * Returns the max precursor charge encountered for the given mgf file. * * @param fileName the name of the mgf file * @return the max precursor charge encountered */ public Integer getMaxCharge(String fileName) { return mgfIndexesMap.get(fileName).getMaxCharge(); } /** * Returns the max precursor charge encountered among all loaded mgf files. * * @return the max precursor charge encountered among all loaded mgf files */ public Integer getMaxCharge() { int maxCharge = 0; for (MgfIndex mgfIndex : mgfIndexesMap.values()) { if (mgfIndex.getMaxCharge() > maxCharge) { maxCharge = mgfIndex.getMaxCharge(); } } return maxCharge; } /** * Returns the max peak count encountered for the given mgf file. * * @param fileName the name of the mgf file * @return the max peak count encountered */ public Integer getMaxPeakCount(String fileName) { return mgfIndexesMap.get(fileName).getMaxPeakCount(); } /** * Returns the max peak count encountered among all loaded mgf files. * * @return the max peak count encountered among all loaded mgf files */ public Integer getMaxPeakCount() { int maxPeakCount = 0; for (MgfIndex mgfIndex : mgfIndexesMap.values()) { if (mgfIndex.getMaxPeakCount() > maxPeakCount) { maxPeakCount = mgfIndex.getMaxPeakCount(); } } return maxPeakCount; } /** * Returns the maximum precursor intensity for the desired file. * * @param fileName the file of interest * @return the max precursor intensity */ public Double getMaxIntensity(String fileName) { return mgfIndexesMap.get(fileName).getMaxIntensity(); } /** * Returns the maximum precursor intensity for the whole project. * * @return the max precursor intensity */ public Double getMaxIntensity() { double maxIntensity = 0; for (MgfIndex mgfIndex : mgfIndexesMap.values()) { if (maxIntensity < mgfIndex.getMaxIntensity()) { maxIntensity = mgfIndex.getMaxIntensity(); } } return maxIntensity; } /** * Returns the maximum retention time in seconds for the desired file. * * @param fileName the file of interest * @return the max RT */ public Double getMaxRT(String fileName) { return mgfIndexesMap.get(fileName).getMaxRT(); } /** * Returns the minimum retention time in seconds for the desired file. * * @param fileName the file of interest * @return the min RT */ public Double getMinRT(String fileName) { return mgfIndexesMap.get(fileName).getMinRT(); } /** * Returns the maximum retention time in seconds for the whole project. * * @return the max RT */ public Double getMaxRT() { double maxRT = 0; for (MgfIndex mgfIndex : mgfIndexesMap.values()) { if (maxRT < mgfIndex.getMaxRT()) { maxRT = mgfIndex.getMaxRT(); } } return maxRT; } /** * Returns the minimum retention time in seconds for the whole project. * * @return the min RT */ public Double getMinRT() { double minRT = Double.MAX_VALUE; for (MgfIndex mgfIndex : mgfIndexesMap.values()) { if (minRT > mgfIndex.getMinRT()) { minRT = mgfIndex.getMinRT(); } } if (minRT == Double.MAX_VALUE) { minRT = 0; } return minRT; } /** * Returns the number of spectra in the desired file. * * @param fileName the file of interest * @return the number of spectra */ public int getNSpectra(String fileName) { return mgfIndexesMap.get(fileName).getNSpectra(); } /** * Returns the total number of spectra in all files. * * @return the total number of spectra in all files */ public int getNSpectra() { int totalSpectrumCount = 0; for (String fileName : mgfIndexesMap.keySet()) { totalSpectrumCount += getNSpectra(fileName); } return totalSpectrumCount; } /** * Returns the precursor of the desired spectrum. * * @param spectrumKey the key of the spectrum * @param save boolean indicating whether the loaded precursor should be * stored in the factory. False by default * @return the corresponding precursor * @throws IOException exception thrown whenever the file was not parsed * correctly * @throws MzMLUnmarshallerException exception thrown whenever the file was * not parsed correctly * @throws IllegalArgumentException exception thrown whenever the file was * not parsed correctly */ public Precursor getPrecursor(String spectrumKey, boolean save) throws IOException, MzMLUnmarshallerException, IllegalArgumentException { String fileName = Spectrum.getSpectrumFile(spectrumKey); String spectrumTitle = Spectrum.getSpectrumTitle(spectrumKey); return getPrecursor(fileName, spectrumTitle, save); } /** * Returns a boolean indicating whether the spectrum file has been loaded. * * @param fileName the file name * @return a boolean indicating whether the spectrum file has been loaded */ public boolean fileLoaded(String fileName) { return mgfIndexesMap.containsKey(fileName); } /** * Returns a boolean indicating whether the spectrum is contained in the * given spectrum file. * * @param fileName the name of the spectrum file * @param spectrumTitle the title of the spectrum * @return a boolean indicating whether the spectrum is contained in the * given spectrum file */ public boolean spectrumLoaded(String fileName, String spectrumTitle) { // a special fix for mgf files with strange titles... spectrumTitle = fixMgfTitle(spectrumTitle, fileName); return mgfIndexesMap.containsKey(fileName) && mgfIndexesMap.get(fileName).containsSpectrum(spectrumTitle); } /** * A boolean indicating whether the spectrum is loaded in the factory. * * @param spectrumKey the spectrum key * @return a boolean indicating whether the spectrum is loaded in the * factory */ public boolean spectrumLoaded(String spectrumKey) { String fileName = Spectrum.getSpectrumFile(spectrumKey); String spectrumTitle = Spectrum.getSpectrumTitle(spectrumKey); return spectrumLoaded(fileName, spectrumTitle); } /** * Returns the precursor of the desired spectrum. It can be that the IO is * busy (especially when working on distant servers) thus returning an * error. The method will then retry after waiting waitingTime milliseconds. * The waitingTime is doubled for the next try. The method throws an * exception after timeout (see timeOut attribute). * * @param spectrumKey the key of the spectrum * @param save boolean indicating whether the loaded precursor should be * stored in the factory * @param waitingTime the waiting time before retry * * @return the corresponding precursor * * @throws IOException exception thrown whenever the file was not parsed * correctly * @throws MzMLUnmarshallerException exception thrown whenever the file was * not parsed correctly * @throws IllegalArgumentException exception thrown whenever the file was * not parsed correctly */ private synchronized Precursor getPrecursor(String fileName, String spectrumTitle, boolean save, long waitingTime) throws IOException, MzMLUnmarshallerException, IllegalArgumentException { if (waitingTime <= 0) { throw new IllegalArgumentException("Waiting time should be a positive number."); } Precursor currentPrecursor = null; if (fileName.toLowerCase().endsWith(".mgf")) { // a special fix for mgf files with strange titles... spectrumTitle = fixMgfTitle(spectrumTitle, fileName); if (mgfIndexesMap.get(fileName) == null) { throw new IOException("Mgf file not found: \'" + fileName + "\'."); } if (mgfIndexesMap.get(fileName).getIndex(spectrumTitle) == null) { throw new IOException("Spectrum \'" + spectrumTitle + "\' in mgf file \'" + fileName + "\' not found."); } try { currentPrecursor = MgfReader.getPrecursor(mgfRandomAccessFilesMap.get(fileName), mgfIndexesMap.get(fileName).getIndex(spectrumTitle), fileName); } catch (Exception e) { if (waitingTime < timeOut) { try { wait(waitingTime); } catch (InterruptedException ie) { } return getPrecursor(fileName, spectrumTitle, save, 2 * waitingTime); } else { e.printStackTrace(); throw new IllegalArgumentException("Error while loading precursor of spectrum " + spectrumTitle + " of file " + fileName + "."); } } } else if (fileName.toLowerCase().endsWith(".mzml")) { uk.ac.ebi.jmzml.model.mzml.Spectrum mzMLSpectrum = mzMLUnmarshallers.get(fileName).getSpectrumById(spectrumTitle); int level = 2; double mzPrec = 0.0; double scanTime = -1.0; int chargePrec = 0; for (CVParam cvParam : mzMLSpectrum.getCvParam()) { if (cvParam.getAccession().equals("MS:1000511")) { level = new Integer(cvParam.getValue()); break; } } ScanList scanList = mzMLSpectrum.getScanList(); if (scanList != null) { for (CVParam cvParam : scanList.getScan().get(scanList.getScan().size() - 1).getCvParam()) { if (cvParam.getAccession().equals("MS:1000016")) { scanTime = new Double(cvParam.getValue()); break; } } } PrecursorList precursorList = mzMLSpectrum.getPrecursorList(); if (precursorList != null) { if (precursorList.getCount().intValue() == 1) { SelectedIonList sIonList = precursorList.getPrecursor().get(0).getSelectedIonList(); if (sIonList != null) { for (CVParam cvParam : sIonList.getSelectedIon().get(0).getCvParam()) { if (cvParam.getAccession().equals("MS:1000744") || cvParam.getAccession().equals("MS:1000040")) { mzPrec = new Double(cvParam.getValue()); } else if (cvParam.getAccession().equals("MS:1000041")) { chargePrec = new Integer(cvParam.getValue()); } } } } } if (level == 1) { throw new IllegalArgumentException("MS1 spectrum"); } else { //@TODO: is this correct..? ArrayList<Charge> charges = new ArrayList<Charge>(); charges.add(new Charge(Charge.PLUS, chargePrec)); currentPrecursor = new Precursor(scanTime, mzPrec, charges); } } else { throw new IllegalArgumentException("Spectrum file format not supported."); } if (save) { HashMap<String, Precursor> fileMap = loadedPrecursorsMap.get(fileName); if (fileMap == null) { fileMap = new HashMap<String, Precursor>(); loadedPrecursorsMap.put(fileName, fileMap); } fileMap.put(spectrumTitle, currentPrecursor); } return currentPrecursor; } /** * Returns the desired spectrum. * * @param spectrumFile name of the spectrum file * @param spectrumTitle title of the spectrum * * @return the desired spectrum * * @throws IOException exception thrown whenever an error occurred while * reading the file * @throws MzMLUnmarshallerException exception thrown whenever an error * occurred while parsing the mzML file */ public Spectrum getSpectrum(String spectrumFile, String spectrumTitle) throws IOException, MzMLUnmarshallerException { HashMap<String, Spectrum> fileMap = currentSpectrumMap.get(spectrumFile); if (fileMap != null) { Spectrum currentSpectrum = fileMap.get(spectrumTitle); if (currentSpectrum != null) { return currentSpectrum; } } return getSpectrum(spectrumFile, spectrumTitle, 1); } /** * Returns the desired spectrum. * * @param spectrumKey key of the spectrum * @return the desired spectrum * @throws IOException exception thrown whenever an error occurred while * reading the file * @throws IllegalArgumentException exception thrown whenever an error * occurred while parsing the file * @throws MzMLUnmarshallerException exception thrown whenever an error * occurred while parsing the file */ public Spectrum getSpectrum(String spectrumKey) throws IOException, MzMLUnmarshallerException { String fileName = Spectrum.getSpectrumFile(spectrumKey); String spectrumTitle = Spectrum.getSpectrumTitle(spectrumKey); return getSpectrum(fileName, spectrumTitle); } /** * Returns the desired spectrum. It can be that the IO is busy (especially * when working on distant servers) thus returning an error. The method will * then retry after waiting waitingTime milliseconds. The waitingTime is * doubled for the next try. The method throws an exception after timeout * (see timeOut attribute). * * @param spectrumFile the name of the file containing the spectrum * @param spectrumTitle the title of the desired spectrum * @param waitingTime the waiting time before retry * * @return the desired spectrum * * @throws IOException exception thrown whenever an error occurred while * reading the file * @throws IllegalArgumentException exception thrown whenever an error * occurred while parsing the file * @throws MzMLUnmarshallerException exception thrown whenever an error * occurred while parsing the file */ private synchronized Spectrum getSpectrum(String spectrumFile, String spectrumTitle, long waitingTime) throws IOException, MzMLUnmarshallerException { if (waitingTime <= 0) { throw new IllegalArgumentException("Waiting time should be a positive number."); } Spectrum currentSpectrum = null; if (spectrumFile.toLowerCase().endsWith(".mgf")) { // a special fix for mgf files with strange titles... spectrumTitle = fixMgfTitle(spectrumTitle, spectrumFile); if (mgfIndexesMap.get(spectrumFile) == null) { throw new FileNotFoundException("Mgf file not found: \'" + spectrumFile + "\'!"); } if (mgfIndexesMap.get(spectrumFile).getIndex(spectrumTitle) == null) { throw new IOException("Spectrum \'" + spectrumTitle + "\' in mgf file \'" + spectrumFile + "\' not found!"); } try { currentSpectrum = MgfReader.getSpectrum(mgfRandomAccessFilesMap.get(spectrumFile), mgfIndexesMap.get(spectrumFile).getIndex(spectrumTitle), spectrumFile); } catch (Exception e) { if (waitingTime < timeOut) { try { wait(waitingTime); } catch (InterruptedException ie) { } return getSpectrum(spectrumFile, spectrumTitle, 2 * waitingTime); } else { e.printStackTrace(); throw new IllegalArgumentException("Error while loading spectrum " + spectrumTitle + " of file " + spectrumFile + "."); } } } else if (spectrumFile.toLowerCase().endsWith(".mzml")) { if (mzMLUnmarshallers.get(spectrumFile) == null) { throw new IOException("mzML file not found: \'" + spectrumFile + "\'!"); } if (mzMLUnmarshallers.get(spectrumFile).getSpectrumById(spectrumTitle) == null) { throw new IOException("Spectrum \'" + spectrumTitle + "\' in mzML file \'" + spectrumFile + "\' not found!"); } uk.ac.ebi.jmzml.model.mzml.Spectrum mzMLSpectrum = mzMLUnmarshallers.get(spectrumFile).getSpectrumById(spectrumTitle); int level = 2; double mzPrec = 0.0; double scanTime = -1.0; int chargePrec = 0; for (CVParam cvParam : mzMLSpectrum.getCvParam()) { if (cvParam.getAccession().equals("MS:1000511")) { level = new Integer(cvParam.getValue()); break; } } ScanList scanList = mzMLSpectrum.getScanList(); if (scanList != null) { for (CVParam cvParam : scanList.getScan().get(scanList.getScan().size() - 1).getCvParam()) { if (cvParam.getAccession().equals("MS:1000016")) { scanTime = new Double(cvParam.getValue()); break; } } } PrecursorList precursorList = mzMLSpectrum.getPrecursorList(); if (precursorList != null) { if (precursorList.getCount().intValue() == 1) { SelectedIonList sIonList = precursorList.getPrecursor().get(0).getSelectedIonList(); if (sIonList != null) { for (CVParam cvParam : sIonList.getSelectedIon().get(0).getCvParam()) { if (cvParam.getAccession().equals("MS:1000744") || cvParam.getAccession().equals("MS:1000040")) { mzPrec = new Double(cvParam.getValue()); } else if (cvParam.getAccession().equals("MS:1000041")) { chargePrec = new Integer(cvParam.getValue()); } } } } } List<BinaryDataArray> bdal = mzMLSpectrum.getBinaryDataArrayList().getBinaryDataArray(); BinaryDataArray mzBinaryDataArray = (BinaryDataArray) bdal.get(0); Number[] mzNumbers = mzBinaryDataArray.getBinaryDataAsNumberArray(); BinaryDataArray intBinaryDataArray = (BinaryDataArray) bdal.get(1); Number[] intNumbers = intBinaryDataArray.getBinaryDataAsNumberArray(); HashMap<Double, Peak> peakList = new HashMap<Double, Peak>(); for (int i = 0; i < mzNumbers.length; i++) { peakList.put(mzNumbers[i].doubleValue(), new Peak(mzNumbers[i].doubleValue(), intNumbers[i].doubleValue(), scanTime)); } if (level == 1) { currentSpectrum = new MS1Spectrum(spectrumFile, spectrumTitle, scanTime, peakList); } else { //@TODO: is this the correct way to set the precursor..? ArrayList<Charge> charges = new ArrayList<Charge>(); charges.add(new Charge(Charge.PLUS, chargePrec)); Precursor precursor = new Precursor(scanTime, mzPrec, charges); currentSpectrum = new MSnSpectrum(level, precursor, spectrumTitle, peakList, spectrumFile, scanTime); } } else { throw new IllegalArgumentException("Spectrum file format not supported."); } if (loadedSpectra.size() == nSpectraCache) { String tempKey = loadedSpectra.pollFirst(); String tempFile = Spectrum.getSpectrumFile(tempKey); HashMap<String, Spectrum> fileMap = currentSpectrumMap.get(tempFile); if (fileMap != null) { String tempTitle = Spectrum.getSpectrumTitle(tempKey); fileMap.remove(tempTitle); } } HashMap<String, Spectrum> fileMap = currentSpectrumMap.get(spectrumFile); if (fileMap == null) { fileMap = new HashMap<String, Spectrum>(); currentSpectrumMap.put(spectrumFile, fileMap); } fileMap.put(spectrumTitle, currentSpectrum); String spectrumKey = Spectrum.getSpectrumKey(spectrumFile, spectrumTitle); loadedSpectra.add(spectrumKey); return currentSpectrum; } /** * Writes the given mgf file index in the given directory. * * @param mgfIndex the mgf file index * @param directory the destination directory * @throws IOException exception thrown whenever an error is encountered * while writing the file */ public void writeIndex(MgfIndex mgfIndex, File directory) throws IOException { File indexFile = new File(directory, getIndexName(mgfIndex.getFileName())); SerializationUtils.writeObject(mgfIndex, indexFile); } /** * Deserializes the index of an mgf file. * * @param mgfIndex the mgf index cui file * @return the corresponding mgf index object * @throws FileNotFoundException exception thrown whenever the file was not * found * @throws IOException exception thrown whenever an error was encountered * while reading the file * @throws ClassNotFoundException exception thrown whenever an error * occurred while deserializing the object */ public MgfIndex getIndex(File mgfIndex) throws FileNotFoundException, IOException, ClassNotFoundException { return (MgfIndex) SerializationUtils.readObject(mgfIndex); } /** * Closes all opened files. * * @throws IOException exception thrown whenever an error occurred while * closing the files */ public void closeFiles() throws IOException { for (BufferedRandomAccessFile randomAccessFile : mgfRandomAccessFilesMap.values()) { randomAccessFile.close(); } } /** * Returns a list of loaded mgf files. * * @return a list of loaded mgf files */ public ArrayList<String> getMgfFileNames() { return new ArrayList<String>(mgfRandomAccessFilesMap.keySet()); } /** * Returns a list of loaded mzML files. * * @return a list of loaded mzML files */ public ArrayList<String> getMzMLFileNames() { return new ArrayList<String>(mzMLUnmarshallers.keySet()); } /** * Returns a list of titles from indexed spectra in the given file. * * @param mgfFile the name of the mgf file * @return a list of titles from indexed spectra in the given file */ public ArrayList<String> getSpectrumTitles(String mgfFile) { MgfIndex index = mgfIndexesMap.get(mgfFile); if (index == null) { return null; } return index.getSpectrumTitles(); } /** * Returns the spectrum index of the given spectrum in the given file. If * the same spectrum title is used more than ones the last index is * returned. Null if not found. * * @param spectrumTitle the spectrum title * @param mgfFile the name of the mgf file * @return the spectrum index of the given spectrum */ public Integer getSpectrumIndex(String spectrumTitle, String mgfFile) { MgfIndex mgfIndex = mgfIndexesMap.get(mgfFile); if (mgfIndex == null) { return null; } return mgfIndex.getSpectrumIndex(spectrumTitle); } /** * Returns the spectrum title of the spectrum of the given number in the * given file. 1 is the first spectrum. Null if not found. * * @param mgfFile the name of the mgf file of interest * @param spectrumNumber the number of the spectrum in the file * * @return the title of the spectrum of interest */ public String getSpectrumTitle(String mgfFile, int spectrumNumber) { MgfIndex mgfIndex = mgfIndexesMap.get(mgfFile); if (mgfIndex == null) { return null; } return mgfIndex.getSpectrumTitle(spectrumNumber - 1); } /** * Returns the fixed mgf title. * * @param spectrumTitle the spectrum title * @param fileName the spectrum file name * @return the fixed mgf title */ private String fixMgfTitle(String spectrumTitle, String fileName) { // a special fix for mgf files with titles containing url encoding, e.g.: %3b instead of ; if (mgfIndexesMap.get(fileName).getIndex(spectrumTitle) == null) { try { spectrumTitle = URLDecoder.decode(spectrumTitle, "utf-8"); } catch (UnsupportedEncodingException e) { System.out.println("An exception was thrown when trying to decode an mgf title: " + spectrumTitle); e.printStackTrace(); } } // a special fix for mgf files with titles containing \\ instead \ if (mgfIndexesMap.get(fileName).getIndex(spectrumTitle) == null) { spectrumTitle = spectrumTitle.replaceAll("\\\\\\\\", "\\\\"); // @TODO: only required for omssa??? } return spectrumTitle; } /** * Adds an id to spectrum name in the mapping. * * @param idName name according to the id file * @param spectrumFile the spectrum file */ public void addIdNameMapping(String idName, File spectrumFile) { idToSpectrumName.put(idName, spectrumFile); } /** * Returns the spectrum file corresponding to the name of the file used for * identification * * @param idName the name of the spectrum file according to the * identification file * @return the spectrum file */ public File getSpectrumFileFromIdName(String idName) { return idToSpectrumName.get(idName); } /** * Returns the file associated to the given name. * * @param fileName the name of the file * * @return the file */ public File getMgfFileFromName(String fileName) { return filesMap.get(fileName); } /** * Returns a map containing all the precursors of a gven file indexed by spectrum title. * * @param fileName the name of the file * * @return a map containing all the precursors of a gven file * * @throws java.io.IOException Exception thrown whenever an error occurs while reading a precursor * @throws uk.ac.ebi.jmzml.xml.io.MzMLUnmarshallerException exception thrown whenever an error occurs while reading an mzML file */ public HashMap<String, Precursor> getPrecursorMap(String fileName) throws IOException, MzMLUnmarshallerException { HashMap<String, Precursor> precursorMap = new HashMap<String, Precursor>(getNSpectra(fileName)); for (String spectrumtitle : getSpectrumTitles(fileName)) { Precursor precursor = getPrecursor(fileName, spectrumtitle); precursorMap.put(spectrumtitle, precursor); } return precursorMap; } }