/* * Copyright (c) 2003-2012 Fred Hutchinson Cancer Research Center * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.fhcrc.cpl.toolbox.proteomics.feature.filehandler; import org.fhcrc.cpl.toolbox.proteomics.feature.FeatureSet; import org.fhcrc.cpl.toolbox.proteomics.feature.Feature; import org.fhcrc.cpl.toolbox.filehandler.TabLoader; import org.apache.log4j.Logger; import java.io.*; import java.util.*; /** * File handler for Hardklor feature files. To be specific, this handles the output format of kronik, * the post-processor for Hardklor output that stitches single-scan features into multi-scan features */ public class HardklorFeatureFileHandler extends BaseFeatureSetFileHandler implements FeatureSetFileHandler { static Logger _log = Logger.getLogger(HardklorFeatureFileHandler.class); public static final String FILE_TYPE_NAME = "HARDKLOR"; protected static HardklorFeatureFileHandler singletonInstance = null; public static HardklorFeatureFileHandler getSingletonInstance() { if (singletonInstance == null) singletonInstance = new HardklorFeatureFileHandler(); return singletonInstance; } /** * Load a FeatureSet * @param file * @return * @throws IOException */ public FeatureSet loadFeatureSet(File file) throws IOException { FeatureSet result = new FeatureSet(); TabLoader loader = new TabLoader(file); TabLoader.ColumnDescriptor[] cols = loader.getColumns(); if (cols.length > 0) { TabLoader.TabLoaderIterator iterator = loader.iterator(); List<Feature>featureList = new ArrayList<Feature>(); while (iterator.hasNext()) { Map<String, Object> rowMap = (Map<String,Object>) iterator.next(); int firstScan = (Integer) rowMap.get("First Scan"); Float mz = ((Double) rowMap.get("Base Isotope Peak")).floatValue(); Float intensity = ((Double) rowMap.get("Best Intensity")).floatValue(); Feature feature = new Feature(firstScan, mz, intensity); feature.setScanFirst(firstScan); feature.setScanLast((Integer) rowMap.get("Last Scan")); feature.setScanCount((Integer) rowMap.get("Num of Scans")); feature.setCharge((Integer) rowMap.get("Charge")); //ignore Hardklor mass because it's one less than base peak mass feature.updateMass(); feature.setTotalIntensity(((Double) rowMap.get("Summed Intensity")).floatValue()); //ignore Hardklor first and last time because we can't store those feature.setTime(((Double) rowMap.get("Best RTime")).floatValue()); featureList.add(feature); } result.setFeatures(featureList.toArray(new Feature[featureList.size()])); } return result; } public void saveFeatureSet(FeatureSet featureSet, File outFile) throws IOException { PrintWriter out = null; assert null != featureSet.getFeatures(); try { out = new PrintWriter(new FileOutputStream(outFile)); saveFeatureSet(featureSet, out); } catch(IOException e) { throw e; } finally { if (out != null) out.close(); } } /** * Save a FeatureSet * @param featureSet * @param out */ public void saveFeatureSet(FeatureSet featureSet, PrintWriter out) { assert null != featureSet.getFeatures(); String header = "File\tFirst Scan\tLast Scan\tNum of Scans\tCharge\tMonoisotopic Mass\tBase Isotope Peak\t" + "Best Intensity\tSummed Intensity\tFirst RTime\tLast RTime\tBest RTime\tBest Correlation\tModifications"; out.println(header); out.flush(); Feature[] features = featureSet.getFeatures(); for (Feature feature : features) { out.println(featureSet.getSourceFile().getAbsolutePath() + "\t" + feature.getScanFirst() + "\t" + feature.getScanLast() + "\t" + feature.getScanCount() + "\t" + feature.getCharge() + "\t" + (feature.getMass() -1) + "\t" + feature.getMz() + "\t" + feature.getIntensity() + "\t" + feature.getTotalIntensity() + "\t" + //we don't store start and end time feature.getTime() + "\t" + feature.getTime() + "\t" + feature.getTime() + "\t" + 0 + "\t" + "_"); } out.flush(); } // TODO: use StringUtils instead private static String join(float[] f, String delim) { if ( null == f || 0 >= f.length ) return null; StringBuffer sb = new StringBuffer(); sb.append("" + f[0]); for(int i = 1; i < f.length; i++) { if ( null != delim) sb.append(delim); sb.append("" + f[i]); } return sb.toString(); } /** * Can this type of file handler handle this specific file? * Implementation is up to the handler, but this should be as low-cost as possible * @param file * @return * @throws IOException */ public boolean canHandleFile(File file) throws IOException { if (isXMLFile(file)) return false; //Check out the first line and look for columns typical of Kronik output FileInputStream fis = new FileInputStream(file); int headerLength = 250; if (fis.available() < headerLength) return false; byte[] headerChars = new byte[headerLength]; if (fis.read(headerChars) < headerLength) return false; String header = new String(headerChars); //check for several things that should be in Kronik files and not in other types return (header.contains("File") && header.contains("First Scan") && header.contains("Best Correlation") && header.contains("Monoisotopic Mass")); } }