/* * The MIT License (MIT) * * Copyright (c) 2007-2015 Broad Institute * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.broad.igv.dev; import org.apache.log4j.Logger; import org.broad.igv.Globals; import org.broad.igv.data.seg.SegmentedAsciiDataSet; import org.broad.igv.dev.db.DBManager; import org.broad.igv.dev.db.DBProfile; import org.broad.igv.dev.db.WholeTableDBReader; import org.broad.igv.exceptions.ParserException; import org.broad.igv.feature.genome.Genome; import org.broad.igv.track.TrackType; import org.broad.igv.util.ParsingUtils; import org.broad.igv.util.ResourceLocator; import htsjdk.tribble.readers.AsciiLineReader; import java.io.IOException; import java.sql.ResultSet; import java.sql.SQLException; /** * Experimental class to explore using the same class as a reader for * both a SQL DB and a file. * * @author Jacob Silterra * @date 2012 Aug 30 */ public class SegmentedReader { private static Logger log = Logger.getLogger(SegmentedReader.class); private Genome genome; private SegmentedAsciiDataSet dataset; private String[] headings; private boolean birdsuite = false; private int sampleColumn = 0; private int chrColumn = 1; private int startColumn = 2; private int endColumn = 3; //int snpCountColumn = 4; // Default value private int dataColumn = 5; private ResourceLocator locator; enum Type { SEG, BIRDSUITE, NEXUS } private class SegmentedDBReader extends WholeTableDBReader<SegmentedAsciiDataSet> { private SegmentedDBReader(DBProfile.DBTable table) { super(table); } @Override protected SegmentedAsciiDataSet processResultSet(ResultSet rs) throws SQLException { IParser<ResultSet, Integer> parser = IParserFactory.getIndexParser(rs); readHeader(rs); while (rs.next()) { parseLine(parser, rs); } DBManager.closeAll(rs); dataset.sortLists(); return dataset; } private int readHeader(ResultSet rs) throws SQLException { dataset = new SegmentedAsciiDataSet(genome); /*sampleColumn = 0; chrColumn = 1; startColumn = 2; endColumn = 3;*/ dataColumn = rs.getMetaData().getColumnCount() - 1; headings = new String[rs.getMetaData().getColumnCount()]; for (int cc = 0; cc < rs.getMetaData().getColumnCount(); cc++) { headings[cc] = rs.getMetaData().getColumnLabel(cc + 1); } return 0; } } public SegmentedReader(ResourceLocator locator) { this(locator, null); } public SegmentedReader(ResourceLocator locator, Genome genome) { this.locator = locator; this.genome = genome; if (locator.getPath().toLowerCase().endsWith("birdseye_canary_calls")) { birdsuite = true; } } /** * Load segmented data from a file could be remote) * Return a map of trackId -> segment datasource * * @return */ public SegmentedAsciiDataSet loadFromFile() { dataset = new SegmentedAsciiDataSet(genome); if (birdsuite) { dataset.setTrackType(TrackType.CNV); } AsciiLineReader reader = null; String nextLine = null; int lineNumber = 0; IParser<String[], Integer> parser = IParserFactory.getIndexParser(new String[0]); try { reader = ParsingUtils.openAsciiReader(locator); lineNumber = readHeader(reader); while ((nextLine = reader.readLine()) != null && (nextLine.trim().length() > 0)) { lineNumber++; String[] tokens = Globals.tabPattern.split(nextLine, -1); parseLine(parser, tokens); } } catch (IOException e) { if (nextLine != null && lineNumber != 0) { throw new ParserException(e.getMessage(), e, lineNumber, nextLine); } else { throw new RuntimeException(e); } } finally { if (reader != null) { reader.close(); } } dataset.sortLists(); return dataset; } public SegmentedAsciiDataSet loadFromDB(DBProfile.DBTable table) { SegmentedDBReader reader = new SegmentedDBReader(table); return reader.load(); } /** * Note: This is an exact copy of the method in ExpressionFileParser. Refactor to merge these * two parsers, or share a common base class. * * @param comment * @param dataset */ private void parseComment(String comment, SegmentedAsciiDataSet dataset) { String tmp = comment.substring(1, comment.length()); if (tmp.startsWith("track")) { ParsingUtils.parseTrackLine(tmp, dataset.getTrackProperties()); } else { String[] tokens = tmp.split("="); String key = tokens[0].trim().toLowerCase(); if (key.equals("type")) { if (tokens.length != 2) { return; } try { dataset.setTrackType(TrackType.valueOf(tokens[1].trim().toUpperCase())); } catch (Exception exception) { log.error("Unknown track type: " + tokens[1].trim().toUpperCase()); } } } } private int readHeader(AsciiLineReader reader) throws IOException { // Parse comments, if any String nextLine = reader.readLine(); int lineNumber = 0; while (nextLine.startsWith("#") || (nextLine.trim().length() == 0)) { lineNumber++; if (nextLine.length() > 0) { parseComment(nextLine, dataset); } nextLine = reader.readLine(); } // Read column headings headings = nextLine.split("\t"); if (birdsuite) { //sample sample_index copy_number chr start end confidence sampleColumn = 0; dataColumn = 2; chrColumn = 3; startColumn = 4; endColumn = 5; } else { sampleColumn = 0; chrColumn = 1; startColumn = 2; endColumn = 3; dataColumn = headings.length - 1; } return lineNumber; } private <TContainer> void parseLine(IParser<TContainer, Integer> parser, TContainer rs) throws ParserException { int nTokens = parser.size(rs); if (nTokens > 4) { String sample = parser.getString(rs, sampleColumn); String chr = parser.getString(rs, chrColumn); int start = parser.getInt(rs, startColumn); int end = parser.getInt(rs, endColumn); float value = parser.getFloat(rs, dataColumn); if (genome != null) { chr = genome.getCanonicalChrName(chr); } String trackId = sample; StringBuffer desc = null; if (birdsuite) { desc = new StringBuffer(); desc.append("<br>"); desc.append(headings[6]); desc.append("="); desc.append(parser.getString(rs, 6)); } else { if (nTokens > 4) { desc = new StringBuffer(); for (int i = 4; i < parser.size(rs) - 1; i++) { desc.append("<br>"); desc.append(headings[i]); desc.append(": "); desc.append(parser.getString(rs, i)); } } } String description = desc == null ? null : desc.toString(); dataset.addSegment(trackId, chr, start, end, value, description); } } }