some quick changes to the VE output system - more to come.
git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@3253 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
parent
7f4d5d9973
commit
c8d09a29ed
|
|
@ -38,6 +38,7 @@ import org.broadinstitute.sting.gatk.refdata.rodDbSNP;
|
|||
import org.broadinstitute.sting.gatk.walkers.RodWalker;
|
||||
import org.broadinstitute.sting.playground.utils.report.ReportMarshaller;
|
||||
import org.broadinstitute.sting.playground.utils.report.VE2ReportFactory;
|
||||
import org.broadinstitute.sting.playground.utils.report.templates.ReportFormat;
|
||||
import org.broadinstitute.sting.playground.utils.report.utils.Node;
|
||||
import org.broadinstitute.sting.utils.classloader.PackageUtils;
|
||||
import org.broadinstitute.sting.utils.StingException;
|
||||
|
|
@ -48,6 +49,7 @@ import org.broadinstitute.sting.utils.text.XReadLines;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
|
|
@ -163,6 +165,8 @@ public class VariantEvalWalker extends RodWalker<Integer, Integer> {
|
|||
@Argument(shortName="reportType", fullName="reportType", doc="If provided, set the template type", required=false)
|
||||
protected VE2ReportFactory.VE2TemplateType reportType = VE2ReportFactory.defaultReportFormat;
|
||||
|
||||
@Argument(shortName="reportLocation", fullName="reportLocation", doc="If provided, set the base file for reports (Required for output formats with more than one file per analysis)", required=false)
|
||||
protected File outputLocation = null;
|
||||
|
||||
Set<String> rsIDsToExclude = null;
|
||||
|
||||
|
|
@ -248,6 +252,9 @@ public class VariantEvalWalker extends RodWalker<Integer, Integer> {
|
|||
// --------------------------------------------------------------------------------------------------------------
|
||||
|
||||
public void initialize() {
|
||||
ReportFormat.AcceptableOutputType type = (outputLocation == null) ? ReportFormat.AcceptableOutputType.STREAM : ReportFormat.AcceptableOutputType.FILE;
|
||||
if (!VE2ReportFactory.isCompatibleWithOutputType(type,reportType))
|
||||
throw new StingException("The report format requested is not compatible with your output location. You specified a " + type + " output type which isn't an option for " + reportType);
|
||||
if ( LIST )
|
||||
listModulesAndExit();
|
||||
|
||||
|
|
@ -289,8 +296,7 @@ public class VariantEvalWalker extends RodWalker<Integer, Integer> {
|
|||
private void listModulesAndExit() {
|
||||
List<Class<? extends VariantEvaluator>> veClasses = PackageUtils.getClassesImplementingInterface(VariantEvaluator.class);
|
||||
out.println("\nAvailable eval modules:");
|
||||
for (int i = 0; i < veClasses.size(); i++)
|
||||
out.println("\t" + veClasses.get(i).getSimpleName());
|
||||
for (Class<? extends VariantEvaluator> veClass : veClasses) out.println("\t" + veClass.getSimpleName());
|
||||
out.println();
|
||||
System.exit(0);
|
||||
}
|
||||
|
|
@ -643,7 +649,14 @@ public class VariantEvalWalker extends RodWalker<Integer, Integer> {
|
|||
}
|
||||
|
||||
public void onTraversalDone(Integer result) {
|
||||
ReportMarshaller marshaller = VE2ReportFactory.createMarhsaller(out,reportType,createExtraOutputTags());
|
||||
// our report mashaller
|
||||
ReportMarshaller marshaller;
|
||||
|
||||
// create the report marshaller early, so that we can fail-fast if something is wrong with the output sources
|
||||
if (outputLocation == null)
|
||||
marshaller = VE2ReportFactory.createMarhsaller(new OutputStreamWriter(out), reportType, createExtraOutputTags());
|
||||
else
|
||||
marshaller = VE2ReportFactory.createMarhsaller(outputLocation, reportType, createExtraOutputTags());
|
||||
for ( String evalName : variantEvaluationNames ) {
|
||||
for ( EvaluationContext group : contexts ) {
|
||||
VariantEvaluator eval = getEvalByName(evalName, group.evaluations);
|
||||
|
|
@ -662,7 +675,7 @@ public class VariantEvalWalker extends RodWalker<Integer, Integer> {
|
|||
* @return a list of nodes to attach to the report as tags
|
||||
*/
|
||||
private List<Node> createExtraOutputTags() {
|
||||
List<Node> list = new ArrayList();
|
||||
List<Node> list = new ArrayList<Node>();
|
||||
list.add(new Node("reference file",getToolkit().getArguments().referenceFile.getName(),"The reference sequence file"));
|
||||
for (String binding : getToolkit().getArguments().RODBindings)
|
||||
list.add(new Node("ROD binding",binding,"The reference sequence file"));
|
||||
|
|
|
|||
|
|
@ -47,21 +47,18 @@ public class ReportMarshaller {
|
|||
|
||||
// the aggregation of all our analyses
|
||||
private Node root;
|
||||
private Writer writeLocation;
|
||||
|
||||
private File outputFileLocation;
|
||||
private Writer outputWriter;
|
||||
/**
|
||||
* create a marshaled object
|
||||
*
|
||||
* @param reportName the report name
|
||||
* @param template the template to use
|
||||
*/
|
||||
public ReportMarshaller(String reportName, File filename, ReportFormat template) {
|
||||
try {
|
||||
init(reportName, new OutputStreamWriter(new FileOutputStream(filename)));
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new StingException("Unable to create Writer from file " + filename,e);
|
||||
}
|
||||
public ReportMarshaller(String reportName, File filename, ReportFormat template, List<Node> reportTags) {
|
||||
temp = template;
|
||||
this.outputFileLocation = filename;
|
||||
createRootNode(reportName, reportTags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -70,37 +67,23 @@ public class ReportMarshaller {
|
|||
* @param reportName the report name
|
||||
*/
|
||||
public ReportMarshaller(String reportName, Writer writer, ReportFormat template, List<Node> reportTags) {
|
||||
init(reportName, writer);
|
||||
this.outputWriter = writer;
|
||||
temp = template;
|
||||
for (Node n : reportTags) {
|
||||
n.setTag();
|
||||
root.addChild(n);
|
||||
}
|
||||
createRootNode(reportName, reportTags);
|
||||
}
|
||||
|
||||
/**
|
||||
* create a marshaled object
|
||||
*
|
||||
* create the root node
|
||||
* @param reportName the report name
|
||||
* @param reportTags the report type
|
||||
*/
|
||||
public ReportMarshaller(String reportName, OutputStream writer, ReportFormat template, List<Node> reportTags) {
|
||||
init(reportName, new PrintWriter(writer));
|
||||
temp = template;
|
||||
for (Node n : reportTags) {
|
||||
n.setTag();
|
||||
root.addChild(n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize the ReportMarshaller
|
||||
* @param reportName the report name
|
||||
* @param writer the output writer
|
||||
*/
|
||||
private void init(String reportName, Writer writer) {
|
||||
private void createRootNode(String reportName, List<Node> reportTags) {
|
||||
root = new Node("report", reportName, DateFormat.getDateTimeInstance().format(new Date()));
|
||||
root.addChild(new Node("title", reportName, "title of the report"));
|
||||
this.writeLocation = writer;
|
||||
for (Node n : reportTags) {
|
||||
n.setTag();
|
||||
root.addChild(n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -190,13 +173,9 @@ public class ReportMarshaller {
|
|||
* call the method to finalize the report
|
||||
*/
|
||||
public void close() {
|
||||
try {
|
||||
temp.write(writeLocation, root);
|
||||
writeLocation.flush();
|
||||
writeLocation.close();
|
||||
} catch (IOException e) {
|
||||
throw new StingException("IO exception", e);
|
||||
}
|
||||
if (outputFileLocation != null) temp.write(outputFileLocation, root);
|
||||
else temp.write(outputWriter, root);
|
||||
temp.close();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -38,15 +38,42 @@ public class VE2ReportFactory {
|
|||
|
||||
/**
|
||||
* create a report ReportMarshaller from a writer, type, and any report tags
|
||||
* @param writer the output object
|
||||
* @param writeTo the output location
|
||||
* @param type the VE2TemplateType type
|
||||
* @param reportTags the tags to append to each report root node
|
||||
* @return a list of ReportMarshallers to write data to
|
||||
*/
|
||||
public static ReportMarshaller createMarhsaller(OutputStream writer,VE2TemplateType type, List<Node> reportTags) {
|
||||
public static ReportMarshaller createMarhsaller(File writeTo,VE2TemplateType type, List<Node> reportTags) {
|
||||
if (!isCompatibleWithOutputType(ReportFormat.AcceptableOutputType.FILE,type))
|
||||
throw new IllegalArgumentException("Report format " + type + " does not support an output parameter of type " + ReportFormat.AcceptableOutputType.FILE);
|
||||
return new ReportMarshaller("Variant Eval 2 Report",writeTo,createByType(type.underlyingReportType),reportTags);
|
||||
}
|
||||
|
||||
/**
|
||||
* create a report ReportMarshaller from a writer, type, and any report tags
|
||||
*
|
||||
* @param writer the output object
|
||||
* @param type the VE2TemplateType type
|
||||
* @param reportTags the tags to append to each report root node
|
||||
*
|
||||
* @return a list of ReportMarshallers to write data to
|
||||
*/
|
||||
public static ReportMarshaller createMarhsaller(Writer writer, VE2TemplateType type, List<Node> reportTags) {
|
||||
if (!isCompatibleWithOutputType(ReportFormat.AcceptableOutputType.STREAM,type))
|
||||
throw new IllegalArgumentException("Report format " + type + " does not support an output parameter of type " + ReportFormat.AcceptableOutputType.STREAM);
|
||||
return new ReportMarshaller("Variant Eval 2 Report",writer,createByType(type.underlyingReportType),reportTags);
|
||||
}
|
||||
|
||||
/**
|
||||
* check that the proposed output type
|
||||
* @param output the output type we're proposing
|
||||
* @param type the report format we'd like to use
|
||||
*/
|
||||
public static boolean isCompatibleWithOutputType( ReportFormat.AcceptableOutputType output, VE2TemplateType type) {
|
||||
ReportFormat format = createByType(type.underlyingReportType);
|
||||
return (format.getAcceptableOutputTypes().contains(output));
|
||||
}
|
||||
|
||||
/**
|
||||
* create a report formatter with the given type
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package org.broadinstitute.sting.playground.utils.report.templates;
|
||||
|
||||
/**
|
||||
* the basic comma seperated value format
|
||||
* the basic comma separated value format
|
||||
*/
|
||||
public class CSVFormat extends TableBasedFormat {
|
||||
private final String DIVIDER = ",";
|
||||
|
||||
private static final String DIVIDER = ",";
|
||||
private static final String extension = ".csv";
|
||||
/**
|
||||
* format the string according to our internal rules
|
||||
*
|
||||
|
|
@ -18,12 +18,42 @@ public class CSVFormat extends TableBasedFormat {
|
|||
}
|
||||
|
||||
/**
|
||||
* does the output format want to display line breaks (dotted lines)?
|
||||
* should we add readability marks?
|
||||
*
|
||||
* @return true if the format uses them
|
||||
* @return true if we should (line breaks, etc)
|
||||
*/
|
||||
@Override
|
||||
public boolean displayDashedLineBreaks() {
|
||||
public boolean addReadabilityMarks() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* a string to prepend for header lines
|
||||
*
|
||||
* @return a string, blank if no string to be appended
|
||||
*/
|
||||
@Override
|
||||
public String headerIndicator() {
|
||||
return "#";
|
||||
}
|
||||
|
||||
/**
|
||||
* should we split the separate files by analysis
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean splitFilesByAnalysis() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* what extension do we want our files to have
|
||||
*
|
||||
* @return a string of the extension
|
||||
*/
|
||||
@Override
|
||||
public String extension() {
|
||||
return extension;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,13 @@
|
|||
package org.broadinstitute.sting.playground.utils.report.templates;
|
||||
|
||||
import org.broadinstitute.sting.playground.utils.report.utils.Node;
|
||||
import org.broadinstitute.sting.utils.StingException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.EnumSet;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -19,12 +23,36 @@ public class GrepFormat implements ReportFormat {
|
|||
|
||||
/**
|
||||
* write out to the writer, given the root node
|
||||
* @param baseFile the writer to write to
|
||||
* @param baseFile the file to write to
|
||||
* @param baseNode the root node
|
||||
*/
|
||||
@Override
|
||||
public void write(File baseFile, Node baseNode) {
|
||||
try {
|
||||
stream = new PrintWriter(baseFile);
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new StingException("Unable to write to file " + baseFile, e);
|
||||
}
|
||||
privateWrite(baseNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* write out to the writer, given the root node
|
||||
*
|
||||
* @param baseFile the file to write to
|
||||
* @param baseNode the root node
|
||||
*/
|
||||
@Override
|
||||
public void write(Writer baseFile, Node baseNode) {
|
||||
stream = new PrintWriter(baseFile);
|
||||
privateWrite(baseNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* write out the node
|
||||
* @param baseNode the base (root) node
|
||||
*/
|
||||
private void privateWrite(Node baseNode) {
|
||||
for (Node analysis : baseNode.getChildren()) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
boolean first = true;
|
||||
|
|
@ -55,4 +83,19 @@ public class GrepFormat implements ReportFormat {
|
|||
recursiveTraverse(child,value + ".[" + nString + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
stream.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* return the valid outputs we support
|
||||
* @return
|
||||
*/
|
||||
public EnumSet<AcceptableOutputType> getAcceptableOutputTypes() {
|
||||
EnumSet<AcceptableOutputType> set = EnumSet.of(AcceptableOutputType.FILE); // always acceptable
|
||||
set.add(AcceptableOutputType.STREAM);
|
||||
return set;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,206 +18,58 @@ import java.util.Map;
|
|||
*
|
||||
* a format for outputting R data - experimental
|
||||
*/
|
||||
public class RFormat implements ReportFormat {
|
||||
private Map<String, List<Node>> analyses = new HashMap<String, List<Node>>();
|
||||
private PrintWriter stream;
|
||||
|
||||
// some reused R table strings
|
||||
private String tempTableName = "temp";
|
||||
private String toTableString = " <- as.table(temp)";
|
||||
private String tableString = tempTableName + " <- matrix(c(";
|
||||
private String rowNamesString = "rownames(" + tempTableName + ") <- c(";
|
||||
private String colNamesString = "colnames(" + tempTableName + ") <- c(";
|
||||
public class RFormat extends TableBasedFormat {
|
||||
private final String DIVIDER = ",";
|
||||
private static final String extension = ".csv";
|
||||
|
||||
/**
|
||||
* write the analyses out
|
||||
* @param writeTo the writer to write to
|
||||
* @param baseNode the base node, containing the analyses
|
||||
* format the string according to our internal rules
|
||||
*
|
||||
* @param str the string to format
|
||||
* @return a string, properly formatted
|
||||
*/
|
||||
@Override
|
||||
public void write(Writer writeTo, Node baseNode) {
|
||||
getAnalyses(baseNode);
|
||||
stream = new PrintWriter(writeTo);
|
||||
for (String s : analyses.keySet()) {
|
||||
writeAnalysis(analyses.get(s));
|
||||
outputTables(analyses.get(s));
|
||||
}
|
||||
public String formatColumn(String str) {
|
||||
return str+DIVIDER;
|
||||
}
|
||||
|
||||
/**
|
||||
* break out the analyses by type, given the base node
|
||||
* should we add readability marks?
|
||||
*
|
||||
* @param baseNode the root node
|
||||
* @return true if we should (line breaks, etc)
|
||||
*/
|
||||
private void getAnalyses(Node baseNode) {
|
||||
for (Node n : baseNode.getChildren())
|
||||
if (!n.tag && n.getComplex()) {
|
||||
if (!analyses.containsKey(n.getValue()))
|
||||
analyses.put(n.getValue(), new ArrayList<Node>());
|
||||
analyses.get(n.getValue()).add(n);
|
||||
}
|
||||
@Override
|
||||
public boolean addReadabilityMarks() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* write the analysis nodes out, only outputting the simple data points (non-table data)
|
||||
* a string to prepend for header lines
|
||||
*
|
||||
* @param nodes a list of nodes, of the same analysis type
|
||||
* @return a string, blank if no string to be appended
|
||||
*/
|
||||
private void writeAnalysis(List<Node> nodes) {
|
||||
if (nodes == null || nodes.size() < 1 || !nodes.get(0).getName().equals("analysis")) return;
|
||||
Node forTitle = nodes.get(0);
|
||||
|
||||
String header = extractHeaderString(forTitle);
|
||||
if (header == null) return; // a null here indicates we don't have any unique columns to display
|
||||
|
||||
StringBuilder rowNameBuilder = new StringBuilder();
|
||||
StringBuilder rowValueBuilder = new StringBuilder();
|
||||
for (Node analysis : nodes) {
|
||||
String dataString = dataPointNodesToValues(analysis);
|
||||
if (dataString.length() > 0 && !dataString.equals("<null>,")) {
|
||||
rowNameBuilder.append("\""+getTagValues(analysis).substring(0,getTagValues(analysis).length() - 1)+"\",");
|
||||
rowValueBuilder.append(dataString);
|
||||
}
|
||||
}
|
||||
stream.print(tableString + rowValueBuilder.toString().substring(0, rowValueBuilder.toString().length() - 1) + "),");
|
||||
stream.println("ncol=" + header.split(",").length + ")");
|
||||
stream.println(rowNamesString + escapeString(rowNameBuilder.toString().substring(0, rowNameBuilder.toString().length() - 1)) + ")");
|
||||
stream.println(colNamesString + escapeString(header.substring(0, header.length() - 1)) + ")");
|
||||
|
||||
stream.println(forTitle.getValue().replace(" ", "_").replace("/","_to_") + toTableString);
|
||||
stream.println();
|
||||
@Override
|
||||
public String headerIndicator() {
|
||||
return "#";
|
||||
}
|
||||
|
||||
/**
|
||||
* output the tables: look at list of analysis nodes (all from the same analysis) and output the table
|
||||
* should we split the seperate files by analysis
|
||||
*
|
||||
* @param nodes the list of analysis nodes (of the same underlying type)
|
||||
* @return
|
||||
*/
|
||||
void outputTables(List<Node> nodes) {
|
||||
Map<String, String> tableRowValues = new HashMap<String, String>();
|
||||
Map<String, String> tableRowNames = new HashMap<String, String>();
|
||||
Map<String, String> tableHeaders = new HashMap<String, String>();
|
||||
Map<String, Integer> columnSizes = new HashMap<String, Integer>();
|
||||
for (Node analysis : nodes)
|
||||
|
||||
for (Node n : analysis.getChildren()) {
|
||||
if (n.table) {
|
||||
StringBuilder columnNamesBuilder = new StringBuilder();
|
||||
StringBuilder rowValueBuilder = new StringBuilder();
|
||||
StringBuilder rowNamesBuilder = new StringBuilder();
|
||||
|
||||
for (Node row : n.getChildren()) {
|
||||
int colSize = 0;
|
||||
rowNamesBuilder.append("\""+getTagValues(analysis));
|
||||
rowNamesBuilder.append(row.getValue()+"\",");
|
||||
for (Node column : row.getChildren()) {
|
||||
columnNamesBuilder.append("\""+column.getValue()+"\",");
|
||||
if (column.getChildren().size() == 1) {
|
||||
String value = column.getChildren().iterator().next().getValue()+",";
|
||||
colSize++;
|
||||
rowValueBuilder.append(value);
|
||||
}
|
||||
}
|
||||
if (!columnSizes.containsKey(n.getValue())) columnSizes.put(n.getValue(),colSize);
|
||||
if (!tableHeaders.containsKey(n.getValue())) {
|
||||
tableHeaders.put(n.getValue(), columnNamesBuilder.toString());
|
||||
}
|
||||
|
||||
}
|
||||
tableRowValues.put(n.getValue(),rowValueBuilder.toString());
|
||||
tableRowNames.put(n.getValue(),rowNamesBuilder.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// output the tables
|
||||
for (String tableName : tableHeaders.keySet()) {
|
||||
stream.print(tableString + tableRowValues.get(tableName).substring(0,tableRowValues.get(tableName).length()-1) + "),");
|
||||
stream.println("ncol="+columnSizes.get(tableName)+")");
|
||||
stream.println(rowNamesString + escapeString(tableRowNames.get(tableName).substring(0,tableRowNames.get(tableName).length()-1)) + ")");
|
||||
stream.println(colNamesString + escapeString(tableHeaders.get(tableName).substring(0,tableHeaders.get(tableName).length()-1)) + ")");
|
||||
|
||||
stream.println(tableName.replace(" ","_") + toTableString);
|
||||
stream.println();
|
||||
}
|
||||
@Override
|
||||
public boolean splitFilesByAnalysis() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the header (tag) names
|
||||
* what extension do we want our files to have
|
||||
*
|
||||
* @param analysis the analysis node
|
||||
*
|
||||
* @return a string representing the tag names
|
||||
* @return a string of the extension
|
||||
*/
|
||||
private String getTagValues(Node analysis) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
for (Node s : analysis.getChildren())
|
||||
if (s.tag) buffer.append(s.getValue()+"_");
|
||||
return buffer.toString();
|
||||
@Override
|
||||
public String extension() {
|
||||
return extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* escape any special characters for R
|
||||
* @param str the string to check
|
||||
* @return the escaped string
|
||||
*/
|
||||
String escapeString(String str) {
|
||||
if (str.contains("/")) str = str.replace("/","\\/");
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* convert the list of nodes to a string
|
||||
*
|
||||
* @param analysis the analysis
|
||||
*
|
||||
* @return a String representing the values
|
||||
*/
|
||||
private String dataPointNodesToValues(Node analysis) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (Node n : analysis.getChildren()) {
|
||||
if (!n.tag && !n.table) {
|
||||
if (n.getChildren().size() > 1)
|
||||
throw new IllegalStateException("Simple data points shouldn't have more than one value");
|
||||
if (n.getChildren().size() == 1)
|
||||
builder.append(formatColumn(n.getChildren().iterator().next().getValue()));
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/** extract the header string from the base analysis node */
|
||||
private String extractHeaderString(Node analysisNode) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
// first get the tags
|
||||
if (!getColumnNames(analysisNode, buffer))
|
||||
return null;
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* get the column names from the analysis node
|
||||
*
|
||||
* @param analysisNode the node
|
||||
* @param buffer the buffer to append to
|
||||
*
|
||||
* @return true if there was data fields to output, false if we don't add data to the column header list
|
||||
*/
|
||||
private boolean getColumnNames(Node analysisNode, StringBuilder buffer) {
|
||||
// now get the simple data points
|
||||
boolean addedValue = false;
|
||||
for (Node n : analysisNode.getChildren())
|
||||
if (!n.tag && !n.table) {
|
||||
addedValue = true;
|
||||
buffer.append(formatColumn(n.getValue()));
|
||||
}
|
||||
return addedValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* format a column string
|
||||
* @param row the column
|
||||
* @return the reformatted string
|
||||
*/
|
||||
public String formatColumn(String row) { return "\"" + row + "\",";}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import org.broadinstitute.sting.playground.utils.report.utils.Node;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.Writer;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* @author aaron
|
||||
|
|
@ -13,5 +14,9 @@ import java.io.Writer;
|
|||
* The basics of a report formatter
|
||||
*/
|
||||
public interface ReportFormat {
|
||||
public void write(Writer baseFile, Node baseNode);
|
||||
public enum AcceptableOutputType { STREAM, FILE };
|
||||
public EnumSet<AcceptableOutputType> getAcceptableOutputTypes();
|
||||
public void write(File fileLocation, Node baseNode);
|
||||
public void write(Writer writeLocation, Node baseNode);
|
||||
public void close();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
package org.broadinstitute.sting.playground.utils.report.templates;
|
||||
|
||||
import org.broadinstitute.sting.playground.utils.report.utils.Node;
|
||||
import org.broadinstitute.sting.utils.StingException;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* an abstract class to share the basics of a table based format; many methods
|
||||
|
|
@ -16,11 +13,42 @@ import java.util.Map;
|
|||
public abstract class TableBasedFormat implements ReportFormat {
|
||||
private Map<String, List<Node>> analyses = new HashMap<String, List<Node>>();
|
||||
private PrintWriter stream;
|
||||
|
||||
private File baseLocation;
|
||||
|
||||
/**
|
||||
* write the base node to the specified writer
|
||||
* @param writeTo the file base to write to
|
||||
* @param baseNode the root node
|
||||
*/
|
||||
@Override
|
||||
public void write(Writer writeTo, Node baseNode) {
|
||||
public void write(File writeTo, Node baseNode) {
|
||||
baseLocation = writeTo;
|
||||
|
||||
// if there is only a single output file, create it
|
||||
if (!splitFilesByAnalysis()) newStream("");
|
||||
|
||||
traverseAnalysisNodes(baseNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* write the base node to the specified writer
|
||||
* @param writeLocation the writer to write to
|
||||
* @param baseNode the root node
|
||||
*/
|
||||
public void write(Writer writeLocation, Node baseNode) {
|
||||
if (splitFilesByAnalysis()) throw new StingException("Unable to write output report, we require a file input for multi-file formats");
|
||||
// if there is only a single output file, create it
|
||||
stream = new PrintWriter(writeLocation);
|
||||
traverseAnalysisNodes(baseNode);
|
||||
stream.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* traverse the analysis nodes, outputting to our stream
|
||||
* @param baseNode the base (root) node, with analysis nodes as children
|
||||
*/
|
||||
private void traverseAnalysisNodes(Node baseNode) {
|
||||
getAnalyses(baseNode);
|
||||
stream = new PrintWriter(writeTo);
|
||||
for (String s : analyses.keySet()) {
|
||||
writeAnalysis(analyses.get(s));
|
||||
outputTables(analyses.get(s));
|
||||
|
|
@ -47,24 +75,24 @@ public abstract class TableBasedFormat implements ReportFormat {
|
|||
private void writeAnalysis(List<Node> nodes) {
|
||||
if (nodes.size() < 1 || !nodes.get(0).getName().equals("analysis")) return;
|
||||
Node forTitle = nodes.get(0);
|
||||
stream.println(niceDivider(80));
|
||||
stream.println("Analysis Name: \t" + forTitle.getValue());
|
||||
stream.println("Analysis Description: \t" + forTitle.getDescription());
|
||||
stream.println();
|
||||
newStream(forTitle.getValue());
|
||||
stream.println(headerIndicator() + "Analysis Name: \t" + forTitle.getValue());
|
||||
stream.println(headerIndicator() + "Analysis Description: \t" + forTitle.getDescription());
|
||||
if (addReadabilityMarks()) stream.println();
|
||||
|
||||
String header = extractHeaderString(forTitle);
|
||||
if (header == null) return; // a null here indicates we don't have any unique columns to display
|
||||
stream.println(header);
|
||||
stream.println(niceDivider(header.length()));
|
||||
stream.println(trimLastChar(header));
|
||||
if (addReadabilityMarks()) stream.println(niceDivider(header.length()));
|
||||
|
||||
for (Node analysis : nodes) {
|
||||
String dataString = dataPointNodesToValues(analysis);
|
||||
if (dataString.length() > 0 && !dataString.equals("<null>")) {
|
||||
stream.print(getTagValues(analysis));
|
||||
stream.println(dataString);
|
||||
stream.println(trimLastChar(dataString));
|
||||
}
|
||||
}
|
||||
stream.println();
|
||||
if (addReadabilityMarks()) stream.println();
|
||||
stream.println();
|
||||
|
||||
}
|
||||
|
|
@ -104,17 +132,21 @@ public abstract class TableBasedFormat implements ReportFormat {
|
|||
|
||||
// output the tables
|
||||
for (String tableName : tableHeaders.keySet()) {
|
||||
stream.println("Table Name : " + tableName);
|
||||
stream.println();
|
||||
stream.println(tableHeaders.get(tableName));
|
||||
stream.println(niceDivider(tableHeaders.get(tableName).length()));
|
||||
newStream(tableName);
|
||||
stream.println(headerIndicator() + "Table Name : " + tableName);
|
||||
stream.println(trimLastChar(tableHeaders.get(tableName)));
|
||||
if (addReadabilityMarks()) stream.println(niceDivider(tableHeaders.get(tableName).length()));
|
||||
List<String> rows = tableRows.get(tableName);
|
||||
for (String row : rows)
|
||||
stream.println(row);
|
||||
stream.println();
|
||||
stream.println(trimLastChar(row));
|
||||
if (addReadabilityMarks()) stream.println();
|
||||
}
|
||||
}
|
||||
|
||||
public String trimLastChar(String toTrim) {
|
||||
return toTrim.substring(0,toTrim.length()-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the header (tag) names
|
||||
* @param analysis the analysis node
|
||||
|
|
@ -185,18 +217,49 @@ public abstract class TableBasedFormat implements ReportFormat {
|
|||
if (n.tag) buffer.append(formatColumn(n.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* this function checks whether we need to create a new stream for the specified analysis
|
||||
*/
|
||||
public void newStream(String analysisOrTableName) {
|
||||
String name = analysisOrTableName.replaceAll("\\s+","_").replaceAll("\\/","_slash_");
|
||||
if (stream == null || splitFilesByAnalysis()) {
|
||||
if (stream != null) stream.close();
|
||||
try {
|
||||
stream = new PrintWriter(this.baseLocation + "." + name + this.extension());
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new StingException("Unable to create Report file at location " + this.baseLocation + "." + name + this.extension(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return the valid outputs we support
|
||||
* @return
|
||||
*/
|
||||
public EnumSet<AcceptableOutputType> getAcceptableOutputTypes() {
|
||||
EnumSet<AcceptableOutputType> set = EnumSet.of(AcceptableOutputType.FILE); // always acceptable
|
||||
if (!splitFilesByAnalysis()) set.add(AcceptableOutputType.STREAM);
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* create a correct-length divider string
|
||||
* @param length the length for the divider
|
||||
* @return a string with the divider text of length "length"
|
||||
*/
|
||||
private String niceDivider(int length) {
|
||||
if (!displayDashedLineBreaks()) return "";
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int x = 0; x < length; x++) builder.append("-");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* close the output file, if open
|
||||
*/
|
||||
public void close() {
|
||||
if (stream != null) stream.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* format the string according to our internal rules
|
||||
* @param str the string to format
|
||||
|
|
@ -205,8 +268,27 @@ public abstract class TableBasedFormat implements ReportFormat {
|
|||
public abstract String formatColumn(String str);
|
||||
|
||||
/**
|
||||
* does the output format want to display line breaks (dotted lines)?
|
||||
* @return true if the format uses them
|
||||
* should we add readability marks?
|
||||
* @return true if we should (line breaks, etc)
|
||||
*/
|
||||
public abstract boolean displayDashedLineBreaks();
|
||||
public abstract boolean addReadabilityMarks();
|
||||
|
||||
|
||||
/**
|
||||
* a string to prepend for header lines
|
||||
* @return a string, blank if no string to be appended
|
||||
*/
|
||||
public abstract String headerIndicator();
|
||||
|
||||
/**
|
||||
* should we split the separate files by analysis
|
||||
* @return
|
||||
*/
|
||||
public abstract boolean splitFilesByAnalysis();
|
||||
|
||||
/**
|
||||
* what extension do we want our files to have
|
||||
* @return a string of the extension
|
||||
*/
|
||||
public abstract String extension();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ package org.broadinstitute.sting.playground.utils.report.templates;
|
|||
*/
|
||||
public class TableFormat extends TableBasedFormat {
|
||||
private static final int COLUMN_WIDTH = 25;
|
||||
|
||||
private static final String TBL = "tbl";
|
||||
|
||||
/**
|
||||
* format the string according to our internal rules
|
||||
*
|
||||
|
|
@ -49,13 +50,43 @@ public class TableFormat extends TableBasedFormat {
|
|||
}
|
||||
|
||||
/**
|
||||
* does the output format want to display line breaks (dotted lines)?
|
||||
* should we add readability marks?
|
||||
*
|
||||
* @return true if the format uses them
|
||||
* @return true if we should (line breaks, etc)
|
||||
*/
|
||||
@Override
|
||||
public boolean displayDashedLineBreaks() {
|
||||
public boolean addReadabilityMarks() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* a string to prepend for header lines
|
||||
*
|
||||
* @return a string, blank if no string to be appended
|
||||
*/
|
||||
@Override
|
||||
public String headerIndicator() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* should we split the seperate files by analysis
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean splitFilesByAnalysis() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* what extension do we want our files to have
|
||||
*
|
||||
* @return a string of the extension
|
||||
*/
|
||||
@Override
|
||||
public String extension() {
|
||||
return TBL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue