001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021package org.biojava.nbio.genome.parsers.gff; 022 023import org.slf4j.Logger; 024import org.slf4j.LoggerFactory; 025 026import java.io.*; 027import java.util.ListIterator; 028 029/** 030 * http://www.bioperl.org/wiki/GTF 031 * Read and write FeatureLists as GFF/GTF formatted files. 032 *<br><br> 033 * The GFF moniker is applied to a variety of tab-delimited formats 034 * that mock the notion of a standard. This class should parse most files 035 * bearing at least a passing resemblance to any of the formats. You will, however, need 036 * to research the semantics of the files you encounter. Generally, 037 * the format consists of 9 tab-delimited fields: 038 * <br> 039 * <pre> 040 * seqname source featureType start end score strand frame attributes 041 * </pre> 042 * The 9th field consists of key-value pairs separated by semicolons, the first of which JavaGene interprets 043 * as the group id (as used in GFF1). It is the precise meaning of this 9th field that 044 * varies from week to week. The Feature and FeatureList objects provide various utility methods to 045 * ease the task of accessing and using the attributes. The proper interpretation of any 046 * particular attribute, however, is left to you. 047 * 048 * @author Hanno Hinsch 049 */ 050public class GeneIDGFF2Reader { 051 052 private static final Logger logger = LoggerFactory.getLogger(GeneIDGFF2Reader.class); 053 054 /** 055 * Read a file into a FeatureList. Each line of the file becomes one Feature object. 056 * 057 * @param filename The path to the GFF file. 058 * @return A FeatureList. 059 * @throws IOException Something went wrong -- check exception detail message. 060 */ 061 public static FeatureList read(String filename) throws IOException { 062 logger.info("Reading: {}", filename); 063 064 FeatureList features = new FeatureList(); 065 BufferedReader br = new BufferedReader(new FileReader(filename)); 066 067 String s; 068 for (s = br.readLine(); null != s; s = br.readLine()) { 069 s = s.trim(); 070 071 if (s.length() > 0) { 072 if (s.charAt(0) == '#') { 073 //ignore comment lines 074 } else { 075 076 FeatureI f = parseLine(s); 077 if (f != null) { 078 features.add(f); 079 } 080 } 081 } 082 083 } 084 085 br.close(); 086 return features; 087 } 088 089 /** 090 * create Feature from line of GFF file 091 */ 092 private static Feature parseLine(String s) { 093 //FIXME update to use regex split on tabs 094 //FIXME better errors on parse failures 095 096 int start = 0; 097 int end = 0; 098 099 start = end; 100 end = s.indexOf('\t', start); 101 String seqname = s.substring(start, end).trim(); 102 103 start = end + 1; 104 end = s.indexOf('\t', start); 105 String source = s.substring(start, end).trim(); 106 107 start = end + 1; 108 end = s.indexOf('\t', start); 109 String type = s.substring(start, end); 110 111 start = end + 1; 112 end = s.indexOf('\t', start); 113 String locStart = s.substring(start, end); 114 115 start = end + 1; 116 end = s.indexOf('\t', start); 117 String locEnd = s.substring(start, end); 118 119 Double score; 120 start = end + 1; 121 end = s.indexOf('\t', start); 122 try { 123 score = Double.parseDouble(s.substring(start, end)); 124 } catch (Exception e) { 125 score = 0.0; 126 } 127 128 start = end + 1; 129 end = s.indexOf('\t', start); 130 char strand = s.charAt(end - 1); 131 132 Location location = Location.fromBio(Integer.parseInt(locStart), Integer.parseInt(locEnd), strand); 133 134 assert (strand == '-') == location.isNegative(); 135 136 int frame; 137 start = end + 1; 138 end = s.indexOf('\t', start); 139 try { 140 frame = Integer.parseInt(s.substring(start, end)); 141 } catch (Exception e) { 142 frame = -1; 143 } 144 145 //grab everything until end of line (or # comment) 146 start = end + 1; 147 end = s.indexOf('#', start); 148 String attributes = null; 149 if (end < 0) { 150 attributes = new String(s.substring(start)); 151 } else { 152 attributes = new String(s.substring(start, end)); 153 } 154 //need to add in attribute assignment for geneid where it just provides a gene name and will make it gtf like 155 attributes = "gene_id " + '"' + attributes + '"' + ";"; 156 return new Feature(seqname, source, type, location, score, frame, attributes); 157 158 } 159 160 /** 161 * Write features in FeatureList to file. Each Feature becomes one line in the file. 162 * The userMap() data in the features is not written to file. 163 * 164 * @param features The list of features to write. 165 * @param filename The path to the file. 166 * @throws IOException Something went wrong -- check exception detail message. 167 */ 168 public static void write(FeatureList features, String filename) throws IOException { 169 logger.info("Writing: {}", filename); 170 171 BufferedWriter bw = new BufferedWriter(new FileWriter(filename)); 172 173 ListIterator<FeatureI> iter = features.listIterator(); 174 while (iter.hasNext()) { 175 Feature feature = (Feature) iter.next(); 176 writeLine(feature, bw); 177 } 178 179 bw.close(); 180 } 181 182 private static void writeLine(Feature f, BufferedWriter bw) throws IOException { 183 String s = f.seqname() + '\t'; 184 s += f.source() + '\t'; 185 s += f.type() + '\t'; 186 187 s += f.location().bioStart() + "\t"; 188 s += f.location().bioEnd() + "\t"; 189 s += Double.toString(f.score()) + "\t"; 190 s += f.location().bioStrand() + "\t"; 191 192 if (f.frame() == -1) { 193 s += ".\t"; 194 } else { 195 s += f.frame() + "\t"; 196 } 197 198 s += f.attributes(); 199 200 bw.write(s); 201 bw.newLine(); 202 } 203 204 205 public static void main(String[] args) throws Exception { 206 207 FeatureList listGenes = GeneIDGFF2Reader.read("/Users/Scooter/scripps/dyadic/analysis/454Scaffolds/genemark_hmm.gtf"); 208 209 for(FeatureI feature : listGenes){ 210 logger.info("Gene Feature: {}", feature); 211 } 212// logger.info(listGenes); 213 // GeneMarkGTF.write( list, args[1] ); 214 } 215}