/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package browser;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.TreeMap;
import org.biojava.bio.BioException;
import org.biojava.bio.program.gff.GFFEntrySet;
import org.biojava.bio.program.gff.GFFFilterer;
import org.biojava.bio.program.gff.GFFParser;
import org.biojava.bio.program.gff.GFFRecord;
import org.biojava.bio.program.gff.GFFRecordFilter;
import org.biojava.bio.seq.StrandedFeature;
import org.biojava.utils.ParserException;
/**
*
* @author brandon
*/
public class GFFConverter {
String gffFileName;
String featureName;
String seqName;
int colorR;
int colorG;
int colorB;
double radiusMultiplier;
double opacity;
boolean isTwoStrandFeature; // should the features cover both strands?
String outFileName;
private ArrayList<TubePosition> tubePositions;
TreeMap<Integer, GFFRecord> sorter;
PrintWriter outFile;
public GFFConverter(String gffFileName, String featureName, String seqName, int colorR, int colorG, int colorB, double radiusMultiplier, double opacity, boolean isTwoStrandFeature) {
this.gffFileName = gffFileName;
this.featureName = featureName;
this.seqName = seqName;
this.colorR = colorR;
this.colorG = colorG;
this.colorB = colorB;
this.radiusMultiplier = radiusMultiplier;
this.opacity = opacity;
this.isTwoStrandFeature = isTwoStrandFeature;
}
public void convert() throws IOException, BioException, ParserException {
// find all of the given feature from the given sequence
GFFEntrySet gffEntries = new GFFEntrySet();
GFFRecordFilter.FeatureFilter fFilter = new GFFRecordFilter.FeatureFilter();
fFilter.setFeature(featureName);
GFFRecordFilter.SequenceFilter sFilter = new GFFRecordFilter.SequenceFilter();
sFilter.setSeqName(seqName);
// have to and the filters together
GFFAndFilter aFilter = new GFFAndFilter(fFilter, sFilter);
GFFFilterer filterer = new GFFFilterer(gffEntries.getAddHandler(), aFilter);
// parse the gff file
GFFParser parser = new GFFParser();
parser.parse(new BufferedReader(new InputStreamReader(new FileInputStream(new File(gffFileName)))), filterer);
// find all of the features
// output to the out file the tube information
//outFile = new PrintWriter(new BufferedWriter(new FileWriter(outFileName)));
Iterator entriesIterator = gffEntries.lineIterator();
// make sure to sort the records
sorter = new TreeMap<Integer, GFFRecord>();
// add everything to the treeMap to ensure it is sorted
while (entriesIterator.hasNext()) {
Object o = entriesIterator.next();
if (o instanceof GFFRecord) {
GFFRecord record = (GFFRecord) o;
sorter.put(record.getStart(), record);
}
}
if(sorter.size() > 0) {
if(isTwoStrandFeature) {
printTwoStrandedFeature();
} else {
printOneStrandedFeature();
}
}
//outFile.close();
}
protected void printTwoStrandedFeature() {
// use 2% of the length of the genome as the radius
// include the radius multiplier for outer features
Integer first = sorter.firstKey();
Integer last = sorter.lastKey();
double radius = (last - first) * 0.02 * radiusMultiplier;
// multiply the radius by 3 because it needs to surround both strands
// it also needs to cover the gap between them
radius *= 3;
//outFile.println("##\t" + opacity);
tubePositions = new ArrayList<TubePosition>();
for(GFFRecord record : sorter.values()) {
TubePosition pre_zero = new TubePosition(record.getStart() - 1, 0, 0, 0, 0, 0, 0.0);
TubePosition data_start = new TubePosition(record.getStart(), 0, 0, colorR, colorG, colorB, radius);
TubePosition data_end = new TubePosition(record.getEnd(), 0, 0, colorR, colorG, colorB, radius);
TubePosition post_zero = new TubePosition(record.getEnd() + 1, 0, 0, 0, 0, 0, 0.0);
getTubePositions().add(pre_zero);
getTubePositions().add(data_start);
getTubePositions().add(data_end);
getTubePositions().add(post_zero);
/*
// print out something with 0 radius right before this entry
outFile.println((record.getStart() - 1) + "\t0\t0\t0\t0\t0\t0.0");
outFile.print(record.getStart() + "\t0\t0\t");
outFile.println(colorR + "\t" + colorG + "\t" + colorB + "\t" + radius);
outFile.print(record.getEnd() + "\t0\t0\t");
outFile.println(colorR + "\t" + colorG + "\t" + colorB + "\t" + radius);
// print out something with 0 radius right after this entry
outFile.println((record.getEnd() + 1) + "\t0\t0\t0\t0\t0\t0.0");
*/
}
}
protected void printOneStrandedFeature() {
// use 2% of the length of the genome as the radius
// include the radius multiplier for outer features
Integer first = sorter.firstKey();
Integer last = sorter.lastKey();
double radius = (last - first) * 0.02 * radiusMultiplier;
tubePositions = new ArrayList<TubePosition>();
// now print the outFile
// the treeMap ensures we get everything out in sorted order
// draw the base negative strand
//outFile.println("##\t" + opacity);
TubePosition first_base_neg = new TubePosition(first, 1.5 * radius, 0, 153, 153, 153, 0.75 * radius);
//outFile.println(first + "\t" + (1.5 * radius) + "\t0\t153\t153\t153\t" + (0.75 * radius));
TubePosition last_base_neg = new TubePosition(last, 1.5 * radius, 0, 153, 153, 153, 0.75 * radius);
//outFile.println(last + "\t" + (1.5 * radius) + "\t0\t153\t153\t153\t" + (0.75 * radius));
getTubePositions().add(first_base_neg);
getTubePositions().add(last_base_neg);
// begin the negative strand track in the cylinder file
// outFile.println("##\t" + opacity);
for(GFFRecord record : sorter.values()) {
if(record.getStrand().equals(StrandedFeature.NEGATIVE) || record.getStrand().equals(StrandedFeature.UNKNOWN)) {
// print out something with 0 radius right before this entry
TubePosition neg_pre_zero = new TubePosition(record.getStart() - 1, 1.5 * radius, 0, 0, 0, 0, 0.0);
//outFile.println((record.getStart() - 1) + "\t" + (1.5 * radius) + "\t0\t0\t0\t0\t0.0");
TubePosition neg_data_start = new TubePosition(record.getStart(), 1.5 * radius, 0, colorR, colorG, colorB, radius);
//outFile.print(record.getStart() + "\t" + (1.5 * radius) + "\t0\t");
//outFile.println(colorR + "\t" + colorG + "\t" + colorB + "\t" + radius);
TubePosition neg_data_end = new TubePosition(record.getEnd(), 1.5 * radius, 0, colorR, colorG, colorB, radius);
//outFile.print(record.getEnd() + "\t" + (1.5 * radius) + "\t0\t");
//outFile.println(colorR + "\t" + colorG + "\t" + colorB + "\t" + radius);
// print out something with 0 radius right after this entry
TubePosition neg_post_zero = new TubePosition(record.getEnd() + 1, 1.5 * radius, 0, 0, 0, 0, 0.0);
//outFile.println((record.getEnd() + 1) + "\t" + (1.5 * radius) + "\t0\t0\t0\t0\t0.0");
getTubePositions().add(neg_pre_zero);
getTubePositions().add(neg_data_start);
getTubePositions().add(neg_data_end);
getTubePositions().add(neg_post_zero);
}
}
// draw the base positive strand
//outFile.println("##\t" + opacity);
TubePosition first_base_pos = new TubePosition(first, -1.5 * radius, 0, 153, 153, 153, 0.75 * radius);
TubePosition last_base_pos = new TubePosition(last, -1.5 * radius, 0, 153, 153, 153, 0.75 * radius);
//outFile.println(first + "\t-" + (1.5 * radius) + "\t0\t153\t153\t153\t" + (0.75 * radius));
//outFile.println(last + "\t-" + (1.5 * radius) + "\t0\t153\t153\t153\t" + (0.75 * radius));
getTubePositions().add(first_base_pos);
getTubePositions().add(last_base_pos);
// begin the positive strand track in the cylinder file
//outFile.println("##\t" + opacity);
for(GFFRecord record : sorter.values()) {
if(record.getStrand().equals(StrandedFeature.POSITIVE) || record.getStrand().equals(StrandedFeature.UNKNOWN)) {
// print out something with 0 radius right before this entry
TubePosition pos_pre_zero = new TubePosition(record.getStart() - 1, -1.5 * radius, 0, 0, 0, 0, 0.0);
//outFile.println((record.getStart() - 1) + "\t-" + (1.5 * radius) + "\t0\t0\t0\t0\t0.0");
TubePosition pos_data_start = new TubePosition(record.getStart(), -1.5 * radius, 0, colorR, colorG, colorB, radius);
TubePosition pos_data_end = new TubePosition(record.getEnd(), -1.5 * radius, 0, colorR, colorG, colorB, radius);
//outFile.print(record.getStart() + "\t-" + (1.5 * radius) + "\t0\t");
//outFile.println(colorR + "\t" + colorG + "\t" + colorB + "\t" + radius);
//outFile.print(record.getEnd() + "\t-" + (1.5 * radius) + "\t0\t");
//outFile.println(colorR + "\t" + colorG + "\t" + colorB + "\t" + radius);
TubePosition pos_post_zero = new TubePosition(record.getEnd() + 1, -1.5 * radius, 0, 0, 0, 0, 0.0);
getTubePositions().add(pos_pre_zero);
getTubePositions().add(pos_data_start);
getTubePositions().add(pos_data_end);
getTubePositions().add(pos_post_zero);
// print out something with 0 radius right after this entry
//outFile.println((record.getEnd() + 1) + "\t-" + (1.5 * radius) + "\t0\t0\t0\t0\t0.0");
}
}
}
/**
* @return the tubePositions
*/
public ArrayList<TubePosition> getTubePositions() {
return tubePositions;
}
}