added some sample annotations to VariantEval2 analysis modules, and some changes to the report system.

git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@3067 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
aaron 2010-03-24 05:40:10 +00:00
parent 1f451e17e5
commit 60dfba997b
10 changed files with 391 additions and 274 deletions

View File

@ -5,39 +5,61 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContext;
import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
import org.broadinstitute.sting.gatk.contexts.variantcontext.VariantContext; import org.broadinstitute.sting.gatk.contexts.variantcontext.VariantContext;
import org.broadinstitute.sting.gatk.contexts.variantcontext.Genotype; import org.broadinstitute.sting.gatk.contexts.variantcontext.Genotype;
import org.broadinstitute.sting.playground.utils.report.tags.Analysis;
import org.broadinstitute.sting.playground.utils.report.tags.DataPoint;
import org.broadinstitute.sting.utils.StingException; import org.broadinstitute.sting.utils.StingException;
import java.util.List; import java.util.List;
import java.util.Arrays; import java.util.Arrays;
@Analysis(name = "Count Variants", description = "Counts different classes of variants in the sample")
public class CountVariants extends VariantEvaluator { public class CountVariants extends VariantEvaluator {
@DataPoint(description = "Number of processed loci")
long nProcessedLoci = 0; long nProcessedLoci = 0;
@DataPoint(description = "Number of called loci")
long nCalledLoci = 0; long nCalledLoci = 0;
@DataPoint(description = "Number of variant loci")
long nVariantLoci = 0; long nVariantLoci = 0;
@DataPoint(description = "Number of reference loci")
long nRefLoci = 0; long nRefLoci = 0;
@DataPoint(description = "Number of snp loci")
long nSNPs = 0; long nSNPs = 0;
@DataPoint(description = "Number of insertions")
long nInsertions = 0; long nInsertions = 0;
@DataPoint(description = "Number of deletions")
long nDeletions = 0; long nDeletions = 0;
@DataPoint(description = "Number of complex loci")
long nComplex = 0; long nComplex = 0;
@DataPoint(description = "Number of no calls loci")
long nNoCalls = 0; long nNoCalls = 0;
@DataPoint(description = "Number of het loci")
long nHets = 0; long nHets = 0;
@DataPoint(description = "Number of hom ref loci")
long nHomRef = 0; long nHomRef = 0;
@DataPoint(description = "Number of hom var loci")
long nHomVar = 0; long nHomVar = 0;
public CountVariants(VariantEval2Walker parent) { public CountVariants(VariantEval2Walker parent) {
// don't do anything // don't do anything
} }
private double perLocusRate(long n) { return rate(n, nProcessedLoci); } private double perLocusRate(long n) {
private long perLocusRInverseRate(long n) { return inverseRate(n, nProcessedLoci); } return rate(n, nProcessedLoci);
}
private long perLocusRInverseRate(long n) {
return inverseRate(n, nProcessedLoci);
}
public String getName() { public String getName() {
return "counter"; return "counter";
} }
public boolean enabled() { return true; } public boolean enabled() {
return true;
}
public int getComparisonOrder() { public int getComparisonOrder() {
return 1; // we only need to see each eval track return 1; // we only need to see each eval track
@ -53,25 +75,41 @@ public class CountVariants extends VariantEvaluator {
if (vc1.isVariant()) nVariantLoci++; if (vc1.isVariant()) nVariantLoci++;
switch (vc1.getType()) { switch (vc1.getType()) {
case NO_VARIATION: nRefLoci++; break; case NO_VARIATION:
case SNP: nSNPs++; break; nRefLoci++;
case INDEL: break;
if ( vc1.isInsertion() ) nInsertions++; else nDeletions++; case SNP:
nSNPs++;
break;
case INDEL:
if (vc1.isInsertion()) nInsertions++;
else nDeletions++;
break;
case MIXED:
nComplex++;
break; break;
case MIXED: nComplex++; break;
} }
for (Genotype g : vc1.getGenotypes().values()) { for (Genotype g : vc1.getGenotypes().values()) {
switch (g.getType()) { switch (g.getType()) {
case NO_CALL: nNoCalls++; break; case NO_CALL:
case HOM_REF: nHomRef++; break; nNoCalls++;
case HET: nHets++; break; break;
case HOM_VAR: nHomVar++; break; case HOM_REF:
default: throw new StingException("BUG: Unexpected genotype type: " + g); nHomRef++;
break;
case HET:
nHets++;
break;
case HOM_VAR:
nHomVar++;
break;
default:
throw new StingException("BUG: Unexpected genotype type: " + g);
} }
} }
return null; // we don't capture any intersting sites return null; // we don't capture any interesting sites
} }
public String toString() { public String toString() {

View File

@ -5,6 +5,8 @@ import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
import org.broadinstitute.sting.gatk.refdata.*; import org.broadinstitute.sting.gatk.refdata.*;
import org.broadinstitute.sting.gatk.contexts.variantcontext.VariantContext; import org.broadinstitute.sting.gatk.contexts.variantcontext.VariantContext;
import org.broadinstitute.sting.gatk.contexts.variantcontext.Allele; import org.broadinstitute.sting.gatk.contexts.variantcontext.Allele;
import org.broadinstitute.sting.playground.utils.report.tags.Analysis;
import org.broadinstitute.sting.playground.utils.report.tags.DataPoint;
import java.util.List; import java.util.List;
import java.util.Arrays; import java.util.Arrays;
@ -18,10 +20,15 @@ import java.util.Arrays;
* This software is supplied without any warranty or guaranteed support whatsoever. Neither * This software is supplied without any warranty or guaranteed support whatsoever. Neither
* the Broad Institute nor MIT can be responsible for its use, misuse, or functionality. * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
*/ */
@Analysis(name = "dbOverlap", description = "the overlap between DbSNP sites and other SNP tracks")
public class DbSNPPercentage extends VariantEvaluator { public class DbSNPPercentage extends VariantEvaluator {
@DataPoint(name = "DbSNP_count", description = "number of DPSNP sites")
private long nDBSNPs = 0; private long nDBSNPs = 0;
@DataPoint(name = "total_count", description = "number of total snp sites")
private long nEvalSNPs = 0; private long nEvalSNPs = 0;
@DataPoint(name = "number_snps_at_dbsnp", description = "number of SNP sites at DPSNP sites")
private long nSNPsAtdbSNPs = 0; private long nSNPsAtdbSNPs = 0;
@DataPoint(name = "number_concordant", description = "number of concordant sites")
private long nConcordant = 0; private long nConcordant = 0;
public DbSNPPercentage(VariantEval2Walker parent) { public DbSNPPercentage(VariantEval2Walker parent) {
@ -36,11 +43,25 @@ public class DbSNPPercentage extends VariantEvaluator {
return 2; // we need to see each eval track and each comp track return 2; // we need to see each eval track and each comp track
} }
public long nDBSNPs() { return nDBSNPs; } public long nDBSNPs() {
public long nEvalSNPs() { return nEvalSNPs; } return nDBSNPs;
public long nSNPsAtdbSNPs() { return nSNPsAtdbSNPs; } }
public long nConcordant() { return nConcordant; }
public long nNovelSites() { return Math.abs(nEvalSNPs() - nSNPsAtdbSNPs()); } public long nEvalSNPs() {
return nEvalSNPs;
}
public long nSNPsAtdbSNPs() {
return nSNPsAtdbSNPs;
}
public long nConcordant() {
return nConcordant;
}
public long nNovelSites() {
return Math.abs(nEvalSNPs() - nSNPsAtdbSNPs());
}
/** /**
@ -48,8 +69,13 @@ public class DbSNPPercentage extends VariantEvaluator {
* *
* @return db rate * @return db rate
*/ */
public double dbSNPRate() { return rate(nSNPsAtdbSNPs(), nEvalSNPs()); } public double dbSNPRate() {
public double concordanceRate() { return rate(nConcordant(), nSNPsAtdbSNPs()); } return rate(nSNPsAtdbSNPs(), nEvalSNPs());
}
public double concordanceRate() {
return rate(nConcordant(), nSNPsAtdbSNPs());
}
public String toString() { public String toString() {
return getName() + ": " + summaryLine(); return getName() + ": " + summaryLine();
@ -65,11 +91,14 @@ public class DbSNPPercentage extends VariantEvaluator {
"n_novel_snps", "percent_eval_in_comp", "concordance_rate"); "n_novel_snps", "percent_eval_in_comp", "concordance_rate");
// making it a table // making it a table
public List<String> getTableHeader() { public List<String> getTableHeader() {
return HEADER; return HEADER;
} }
public boolean enabled() { return true; } public boolean enabled() {
return true;
}
public List<List<String>> getTableRows() { public List<List<String>> getTableRows() {
return Arrays.asList(Arrays.asList(summaryLine().split(" "))); return Arrays.asList(Arrays.asList(summaryLine().split(" ")));

View File

@ -3,6 +3,10 @@ package org.broadinstitute.sting.oneoffprojects.walkers.varianteval2;
import org.broadinstitute.sting.gatk.contexts.*; import org.broadinstitute.sting.gatk.contexts.*;
import org.broadinstitute.sting.gatk.refdata.*; import org.broadinstitute.sting.gatk.refdata.*;
import org.broadinstitute.sting.gatk.contexts.variantcontext.*; import org.broadinstitute.sting.gatk.contexts.variantcontext.*;
import org.broadinstitute.sting.playground.utils.report.tags.Analysis;
import org.broadinstitute.sting.playground.utils.report.tags.DataPoint;
import org.broadinstitute.sting.playground.utils.report.tags.Param;
import org.broadinstitute.sting.playground.utils.report.utils.TableType;
import org.broadinstitute.sting.utils.StingException; import org.broadinstitute.sting.utils.StingException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -17,17 +21,44 @@ import java.util.*;
* This software is supplied without any warranty or guaranteed support whatsoever. Neither * This software is supplied without any warranty or guaranteed support whatsoever. Neither
* the Broad Institute nor MIT can be responsible for its use, misuse, or functionality. * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
*/ */
@Analysis(name = "Genotype Concordance", description = "Determine the genotype concordance between the genotypes in difference tracks")
public class GenotypeConcordance extends VariantEvaluator { public class GenotypeConcordance extends VariantEvaluator {
protected static Logger logger = Logger.getLogger(GenotypeConcordance.class); protected static Logger logger = Logger.getLogger(GenotypeConcordance.class);
// a mapping from allele count to stats
@DataPoint(description = "the frequency statistics for each allele")
private HashMap<Integer, FrequencyStats> alleleCountStats = new HashMap<Integer, FrequencyStats>();
// a mapping from sample to stats
@DataPoint(description = "the concordance statistics for each sample")
private HashMap<String, SampleStats> concordanceStats = null;
private static final int MAX_MISSED_VALIDATION_DATA = 10000; private static final int MAX_MISSED_VALIDATION_DATA = 10000;
private static final int nGenotypeTypes = Genotype.Type.values().length; private static final int nGenotypeTypes = Genotype.Type.values().length;
class SampleStats { class SampleStats implements TableType {
long[][] concordance = new long[nGenotypeTypes][nGenotypeTypes]; long[][] concordance = new long[nGenotypeTypes][nGenotypeTypes];
// TableType methods
public Object[] getRowKeys() {
return Genotype.Type.values();
}
public Object[] getColumnKeys() {
return Genotype.Type.values();
}
public String getCell(int x, int y) {
return String.valueOf(concordance[x][y]);
}
public String getName() {
return "SampleStats";
}
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
for (int truth = 0; truth < nGenotypeTypes; truth++) { for (int truth = 0; truth < nGenotypeTypes; truth++) {
@ -48,22 +79,33 @@ public class GenotypeConcordance extends VariantEvaluator {
} }
} }
class FrequencyStats { class FrequencyStats implements TableType {
long nFound = 0; long nFound = 0;
long nMissed = 0; long nMissed = 0;
public Object[] getRowKeys() {
return new String[]{"sample"};
}
public Object[] getColumnKeys() {
return new String[]{"number_found", "number_missing"};
}
public String getName() {
return "FrequencyStats";
}
public String getCell(int x, int y) {
if (y == 0) return String.valueOf(nFound);
else return String.valueOf(nMissed);
}
public String toString() { public String toString() {
long total = nFound + nMissed; long total = nFound + nMissed;
return String.format("%d %d %.2f ", nFound, nMissed, total == 0 ? 0.0 : (100.0 * rate(nFound, total))); return String.format("%d %d %.2f ", nFound, nMissed, total == 0 ? 0.0 : (100.0 * rate(nFound, total)));
} }
} }
// a mapping from allele count to stats
private HashMap<Integer, FrequencyStats> alleleCountStats = new HashMap<Integer, FrequencyStats>();
// a mapping from sample to stats
private HashMap<String, SampleStats> concordanceStats = null;
// keep a list of the validation data we saw before the first eval data // keep a list of the validation data we saw before the first eval data
private HashSet<VariantContext> missedValidationData = new HashSet<VariantContext>(); private HashSet<VariantContext> missedValidationData = new HashSet<VariantContext>();
@ -80,7 +122,9 @@ public class GenotypeConcordance extends VariantEvaluator {
return 2; // we need to see each eval track and each comp track return 2; // we need to see each eval track and each comp track
} }
public boolean enabled() { return true; } public boolean enabled() {
return true;
}
public String toString() { public String toString() {
return getName() + ": " + getTableRows(); return getName() + ": " + getTableRows();
@ -99,6 +143,7 @@ public class GenotypeConcordance extends VariantEvaluator {
Arrays.asList("alleleCount", "n_found", "n_missed", "%_found"); Arrays.asList("alleleCount", "n_found", "n_missed", "%_found");
// making it a table // making it a table
public List<String> getTableHeader() { public List<String> getTableHeader() {
ArrayList<String> header = new ArrayList<String>(); ArrayList<String> header = new ArrayList<String>();
header.addAll(SAMPLE_HEADER); header.addAll(SAMPLE_HEADER);
@ -123,6 +168,7 @@ public class GenotypeConcordance extends VariantEvaluator {
} }
private boolean warnedAboutValidationData = false; private boolean warnedAboutValidationData = false;
public String update2(VariantContext eval, VariantContext validation, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) { public String update2(VariantContext eval, VariantContext validation, RefMetaDataTracker tracker, ReferenceContext ref, AlignmentContext context) {
String interesting = null; String interesting = null;

View File

@ -6,6 +6,8 @@ import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
import org.broadinstitute.sting.gatk.contexts.variantcontext.VariantContext; import org.broadinstitute.sting.gatk.contexts.variantcontext.VariantContext;
import org.broadinstitute.sting.gatk.contexts.variantcontext.Genotype; import org.broadinstitute.sting.gatk.contexts.variantcontext.Genotype;
import org.broadinstitute.sting.gatk.contexts.variantcontext.Allele; import org.broadinstitute.sting.gatk.contexts.variantcontext.Allele;
import org.broadinstitute.sting.playground.utils.report.tags.Analysis;
import org.broadinstitute.sting.playground.utils.report.tags.DataPoint;
import org.broadinstitute.sting.utils.StingException; import org.broadinstitute.sting.utils.StingException;
import java.util.List; import java.util.List;
@ -15,36 +17,51 @@ import java.util.regex.Matcher;
/** /**
* Mendelian violation detection and counting * Mendelian violation detection and counting
* * <p/>
* a violation looks like: * a violation looks like:
* Suppose dad = A/B and mom = C/D * Suppose dad = A/B and mom = C/D
* The child can be [A or B] / [C or D]. * The child can be [A or B] / [C or D].
* If the child doesn't match this, the site is a violation * If the child doesn't match this, the site is a violation
* * <p/>
* Some examples: * Some examples:
* * <p/>
* mom = A/A, dad = C/C * mom = A/A, dad = C/C
* child can be A/C only * child can be A/C only
* * <p/>
* mom = A/C, dad = C/C * mom = A/C, dad = C/C
* child can be A/C or C/C * child can be A/C or C/C
* * <p/>
* mom = A/C, dad = A/C * mom = A/C, dad = A/C
* child can be A/A, A/C, C/C * child can be A/A, A/C, C/C
* * <p/>
* The easiest way to do this calculation is to: * The easiest way to do this calculation is to:
* * <p/>
* Get alleles for mom => A/B * Get alleles for mom => A/B
* Get alleles for dad => C/D * Get alleles for dad => C/D
* Make allowed genotypes for child: A/C, A/D, B/C, B/D * Make allowed genotypes for child: A/C, A/D, B/C, B/D
* Check that the child is one of these. * Check that the child is one of these.
*/ */
@Analysis(name = "Mendelian Violation Evaluator", description = "Mendelian Violation Evaluator")
public class MendelianViolationEvaluator extends VariantEvaluator { public class MendelianViolationEvaluator extends VariantEvaluator {
long nVariants, nViolations;
TrioStructure trio; @DataPoint(name = "number_variants", description = "Number of mendelian variants found")
long nVariants;
@DataPoint(name = "number_violations", description = "Number of mendelian violations found")
long nViolations;
@DataPoint(description = "number of child hom ref calls where the parent was hom variant")
long KidHomRef_ParentHomVar;
@DataPoint(description = "number of child het calls where the parent was hom ref")
long KidHet_ParentsHomRef;
@DataPoint(description = "number of child het calls where the parent was hom variant")
long KidHet_ParentsHomVar;
@DataPoint(description = "number of child hom variant calls where the parent was hom ref")
long KidHomVar_ParentHomRef;
VariantEval2Walker parent; VariantEval2Walker parent;
long KidHomRef_ParentHomVar, KidHet_ParentsHomRef, KidHet_ParentsHomVar, KidHomVar_ParentHomRef; TrioStructure trio;
private static Pattern FAMILY_PATTERN = Pattern.compile("(.*)\\+(.*)=(.*)"); private static Pattern FAMILY_PATTERN = Pattern.compile("(.*)\\+(.*)=(.*)");
@ -173,6 +190,7 @@ public class MendelianViolationEvaluator extends VariantEvaluator {
Arrays.asList("nVariants", "nViolations", "KidHomRef_ParentHomVar", "KidHet_ParentsHomRef", "KidHet_ParentsHomVar", "KidHomVar_ParentHomRef"); Arrays.asList("nVariants", "nViolations", "KidHomRef_ParentHomVar", "KidHet_ParentsHomRef", "KidHet_ParentsHomVar", "KidHomVar_ParentHomRef");
// making it a table // making it a table
public List<String> getTableHeader() { public List<String> getTableHeader() {
return HEADER; return HEADER;
} }

View File

@ -4,19 +4,31 @@ import org.broadinstitute.sting.gatk.refdata.RefMetaDataTracker;
import org.broadinstitute.sting.gatk.contexts.AlignmentContext; import org.broadinstitute.sting.gatk.contexts.AlignmentContext;
import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
import org.broadinstitute.sting.gatk.contexts.variantcontext.VariantContext; import org.broadinstitute.sting.gatk.contexts.variantcontext.VariantContext;
import org.broadinstitute.sting.playground.utils.report.tags.Analysis;
import org.broadinstitute.sting.playground.utils.report.tags.DataPoint;
import java.util.List; import java.util.List;
import java.util.Arrays; import java.util.Arrays;
@Analysis(name = "Ti/Tv Variant Evaluator", description = "Ti/Tv Variant Evaluator")
public class TiTvVariantEvaluator extends VariantEvaluator { public class TiTvVariantEvaluator extends VariantEvaluator {
long nTi = 0, nTv = 0;
long nTiInStd = 0, nTvInStd = 0; @DataPoint(name = "ti_count", description = "number of transition loci")
long nTi = 0;
@DataPoint(name = "tv_count", description = "number of transversion loci")
long nTv = 0;
@DataPoint(name = "ti_count_std", description = "number of transition sites in the std")
long nTiInStd = 0;
@DataPoint(name = "tv_count_std", description = "number of transversion sites in the std")
long nTvInStd = 0;
public TiTvVariantEvaluator(VariantEval2Walker parent) { public TiTvVariantEvaluator(VariantEval2Walker parent) {
// don't do anything // don't do anything
} }
public boolean enabled() { return true; } public boolean enabled() {
return true;
}
public String getName() { public String getName() {
return "titv"; return "titv";
@ -29,9 +41,11 @@ public class TiTvVariantEvaluator extends VariantEvaluator {
public void updateTiTv(VariantContext vc, boolean updateStandard) { public void updateTiTv(VariantContext vc, boolean updateStandard) {
if (vc != null && vc.isSNP() && vc.isBiallelic()) { if (vc != null && vc.isSNP() && vc.isBiallelic()) {
if (vc.isTransition()) { if (vc.isTransition()) {
if ( updateStandard ) nTiInStd++; else nTi++; if (updateStandard) nTiInStd++;
else nTi++;
} else { } else {
if ( updateStandard ) nTvInStd++; else nTv++; if (updateStandard) nTvInStd++;
else nTv++;
} }
} }
} }

View File

@ -4,6 +4,7 @@ import org.broadinstitute.sting.gatk.contexts.AlignmentContext;
import org.broadinstitute.sting.gatk.contexts.ReferenceContext; import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
import org.broadinstitute.sting.gatk.refdata.*; import org.broadinstitute.sting.gatk.refdata.*;
import org.broadinstitute.sting.gatk.contexts.variantcontext.VariantContext; import org.broadinstitute.sting.gatk.contexts.variantcontext.VariantContext;
import org.broadinstitute.sting.playground.utils.report.tags.Analysis;
import java.util.List; import java.util.List;
import java.util.Arrays; import java.util.Arrays;
@ -17,6 +18,7 @@ import java.util.Arrays;
* This software is supplied without any warranty or guaranteed support whatsoever. Neither * This software is supplied without any warranty or guaranteed support whatsoever. Neither
* the Broad Institute nor MIT can be responsible for its use, misuse, or functionality. * the Broad Institute nor MIT can be responsible for its use, misuse, or functionality.
*/ */
@Analysis(name = "Validation Rate", description = "Validation Rate")
public class ValidationRate extends VariantEvaluator { public class ValidationRate extends VariantEvaluator {
// todo -- subset validation data by list of samples, if provided // todo -- subset validation data by list of samples, if provided
@ -26,7 +28,9 @@ public class ValidationRate extends VariantEvaluator {
class SiteStats { class SiteStats {
long nPoly = 0, nMono = 0, nNoCall = 0; long nPoly = 0, nMono = 0, nNoCall = 0;
double polyPercent() { return 100 * rate(nPoly, nPoly + nMono + nNoCall); } double polyPercent() {
return 100 * rate(nPoly, nPoly + nMono + nNoCall);
}
} }
private SiteStats validationStats = new SiteStats(); private SiteStats validationStats = new SiteStats();
@ -68,11 +72,14 @@ public class ValidationRate extends VariantEvaluator {
"PPV", "Sensitivity"); "PPV", "Sensitivity");
// making it a table // making it a table
public List<String> getTableHeader() { public List<String> getTableHeader() {
return HEADER; return HEADER;
} }
public boolean enabled() { return true; } public boolean enabled() {
return true;
}
public List<List<String>> getTableRows() { public List<List<String>> getTableRows() {
return Arrays.asList(Arrays.asList(summaryLine().split(" "))); return Arrays.asList(Arrays.asList(summaryLine().split(" ")));
@ -89,8 +96,7 @@ public class ValidationRate extends VariantEvaluator {
overlap = evalOverlapAtPoly; overlap = evalOverlapAtPoly;
if (eval == null || eval.isMonomorphic()) if (eval == null || eval.isMonomorphic())
interesting = "ValidationStatus=FN"; interesting = "ValidationStatus=FN";
} } else {
else {
validationStats.nMono++; validationStats.nMono++;
overlap = evalOverlapAtMono; overlap = evalOverlapAtMono;

View File

@ -33,10 +33,7 @@ import org.broadinstitute.sting.utils.StingException;
import java.io.*; import java.io.*;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/** /**
@ -52,6 +49,7 @@ public class ReportMarshaller {
// the aggregation of all our analyses // the aggregation of all our analyses
private Node root; private Node root;
private File writeLocation; private File writeLocation;
/** /**
* create a marshaled object * create a marshaled object
* *
@ -64,10 +62,8 @@ public class ReportMarshaller {
} }
private void init(String reportName, File filename) { private void init(String reportName, File filename) {
root = new Node(reportName); root = new Node("report", reportName, "the overarching report object");
Node title= new Node("title"); root.addChild(new Node("title", reportName, "title of the report"));
title.addChild(new Node(reportName));
root.addChild(title);
this.writeLocation = filename; this.writeLocation = filename;
} }
@ -101,12 +97,40 @@ public class ReportMarshaller {
root.addChild(analysis); root.addChild(analysis);
} }
/**
* add an analysis module to the output source
*
* @param toMarshall the object to marshall
*/
public void write(List<Node> prependNodes, Object toMarshall) {
// Create a context to add data to
HashMap analysisMap = new HashMap();
AnalysisModuleScanner moduleScanner = new AnalysisModuleScanner(toMarshall);
Node analysis = addAnalysis(moduleScanner);
analysis.addAllChildren(getParameterNodes(toMarshall, moduleScanner));
analysis.addAllChildren(getDataPointNodes(toMarshall, moduleScanner));
// prepend the list of nodes passed in
Node currChild = null;
for (Node n : prependNodes) {
if (currChild == null) {
root.addChild(n);
currChild = n;
} else {
currChild.addChild(n);
currChild = n;
}
}
// add this analysis to the root node
if (currChild == null) root.addChild(analysis);
else currChild.addChild(analysis);
}
private Node addAnalysis(AnalysisModuleScanner moduleScanner) { private Node addAnalysis(AnalysisModuleScanner moduleScanner) {
Node analysis = new Node(moduleScanner.getAnalysis().name()); return new Node("analysis", moduleScanner.getAnalysis().name(), moduleScanner.getAnalysis().description());
Node description = new Node("description");
description.createSubNode(moduleScanner.getAnalysis().description());
analysis.addChild(description);
return analysis;
} }
/** /**
@ -119,7 +143,9 @@ public class ReportMarshaller {
private Collection<Node> getParameterNodes(Object toMarshall, AnalysisModuleScanner moduleScanner) { private Collection<Node> getParameterNodes(Object toMarshall, AnalysisModuleScanner moduleScanner) {
Collection<Node> nodes = new ArrayList<Node>(); Collection<Node> nodes = new ArrayList<Node>();
for (Field f : moduleScanner.getParameters().keySet()) { for (Field f : moduleScanner.getParameters().keySet()) {
Node node = new Node(moduleScanner.getParameters().get(f).name().equals("") ? f.getName() : moduleScanner.getParameters().get(f).name()); Node node = new Node("parameter",
moduleScanner.getParameters().get(f).name().equals("") ? f.getName() : moduleScanner.getParameters().get(f).name(),
moduleScanner.getParameters().get(f).description());
addChildNodeFromField(toMarshall, f, node); addChildNodeFromField(toMarshall, f, node);
nodes.add(node); nodes.add(node);
} }
@ -136,14 +162,18 @@ public class ReportMarshaller {
private Collection<Node> getDataPointNodes(Object toMarshall, AnalysisModuleScanner moduleScanner) { private Collection<Node> getDataPointNodes(Object toMarshall, AnalysisModuleScanner moduleScanner) {
Collection<Node> nodes = new ArrayList<Node>(); Collection<Node> nodes = new ArrayList<Node>();
for (Field f : moduleScanner.getData().keySet()) { for (Field f : moduleScanner.getData().keySet()) {
Node node = new Node(moduleScanner.getData().get(f).name().equals("") ? f.getName() : moduleScanner.getData().get(f).name()); Node node = new Node("data_point",
moduleScanner.getData().get(f).name().equals("") ? f.getName() : moduleScanner.getData().get(f).name(),
moduleScanner.getData().get(f).description());
addChildNodeFromField(toMarshall, f, node); addChildNodeFromField(toMarshall, f, node);
nodes.add(node); nodes.add(node);
} }
return nodes; return nodes;
} }
/** call the method to finalize the report */ /**
* call the method to finalize the report
*/
public void close() { public void close() {
Writer out = null; Writer out = null;
try { try {
@ -174,7 +204,7 @@ public class ReportMarshaller {
cfg.setObjectWrapper(new DefaultObjectWrapper()); cfg.setObjectWrapper(new DefaultObjectWrapper());
Template temp = null; Template temp = null;
try { try {
temp = cfg.getTemplate("machineReadable.ftl"); temp = cfg.getTemplate("myTestTemp.ftl"); // TODO: obviously this has to be changed to a factory or something like that
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -183,6 +213,7 @@ public class ReportMarshaller {
/** /**
* helper method for adding a Node to the specified node, given the field * helper method for adding a Node to the specified node, given the field
*
* @param toMarshall the object which contains the specified field * @param toMarshall the object which contains the specified field
* @param f the field * @param f the field
* @param node the node to add a child node to * @param node the node to add a child node to

View File

@ -1,99 +0,0 @@
/*
* Copyright (c) 2010. The 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.broadinstitute.sting.playground.utils.report;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
*
* @author aaron
*
* Class TableFormatter
*
* a helper class for formatting a table of data. Given a collection, it formats it into rows and columns.
* If it's a Map, values are emited as key, value, key, value, so it may make sense to have colums set to 2.
*
* TODO: Needs some cleanup
*
*/
public class TableFormatter {
public Object tableEntries; // data storage
private int columns = 2; // default to two columns of data, overridden in the constructor
public TableFormatter(Collection<Object> tbl, int columns) {
tableEntries = tbl;
this.columns = columns;
}
public TableFormatter(Object tbl) {
tableEntries = tbl;
}
/**
* convert the underlying object to a list of lists, for convenient output
* @return a list of list of objects (a list for each row, then a list of row members)
*/
public List<List<Object>> toRows() {
if (tableEntries instanceof Collection)
return collectionToTable(((Collection)tableEntries));
else if (tableEntries instanceof Map)
return mapToTable(((Map)tableEntries));
else
throw new UnsupportedOperationException("underlying collection must be an instance of type Collection or of type Map");
}
private List<List<Object>> mapToTable(Map collection) {
ArrayList<List<Object>> list = new ArrayList<List<Object>>();
for (Object obj : collection.keySet()) {
List<Object> currentRow = new ArrayList<Object>();
currentRow.add(obj);
Object data = collection.get(obj);
currentRow.add(data.toString());
list.add(currentRow);
}
return list;
}
private List<List<Object>> collectionToTable(Collection collection) {
ArrayList<List<Object>> list = new ArrayList<List<Object>>();
List<Object> currentRow = new ArrayList<Object>();
for (Object obj : collection) {
if (currentRow.size() >= columns) {
list.add(currentRow);
currentRow = new ArrayList<Object>();
}
currentRow.add(obj);
}
list.add(currentRow);
return list;
}
}

View File

@ -1,20 +1,22 @@
package org.broadinstitute.sting.playground.utils.report.utils; package org.broadinstitute.sting.playground.utils.report.utils;
import org.broadinstitute.sting.utils.Utils;
import java.util.*; import java.util.*;
/** /**
*
* @author aaron * @author aaron
* * <p/>
* Class ComplexDataUtils * Class ComplexDataUtils
* * <p/>
* This class contains methods and techniques for breaking down complex data in the output system * This class contains methods and techniques for breaking down complex data in the output system
*/ */
public class ComplexDataUtils { public class ComplexDataUtils {
/** /**
* convert any string -> object pairing into a string keyed tree * convert any string -> object pairing into a string keyed tree
*
* @param obj the object * @param obj the object
* @return a mapping of the name to the associated value tree. All non-leaf nodes will be Strings * @return a mapping of the name to the associated value tree. All non-leaf nodes will be Strings
*/ */
@ -22,12 +24,13 @@ public class ComplexDataUtils {
Collection<Node> nodes = new ArrayList<Node>(); Collection<Node> nodes = new ArrayList<Node>();
// the simplest case // the simplest case
if (obj == null) nodes.add(new Node("<null>")); // throw new IllegalStateException("object is null"); if (obj == null)
nodes.add(new Node("<null>", "<null>", "<null>")); // throw new IllegalStateException("object is null");
else if (obj instanceof TableType) else if (obj instanceof TableType)
nodes.add(tableToNode((TableType) obj, ((TableType) obj).getName())); nodes.add(tableToNode((TableType) obj, ((TableType) obj).getName()));
else if (obj instanceof Map) { else if (obj instanceof Map) {
for (Object key : ((Map) obj).keySet()) { for (Object key : ((Map) obj).keySet()) {
Node keyNode = new Node(key.toString()); Node keyNode = new Node("key", key.toString(), "map key");
nodes.add(keyNode); nodes.add(keyNode);
keyNode.addAllChildren(resolveObjects(((Map) obj).get(key))); keyNode.addAllChildren(resolveObjects(((Map) obj).get(key)));
} }
@ -36,27 +39,35 @@ public class ComplexDataUtils {
else if (obj.getClass().isArray()) else if (obj.getClass().isArray())
nodes.addAll(listToNode(Arrays.asList(obj), "array")); nodes.addAll(listToNode(Arrays.asList(obj), "array"));
else else
nodes.add(new Node(obj.toString())); nodes.add(new Node(obj.getClass().getSimpleName(), obj.toString(), "value"));
return nodes; return nodes;
} }
/** /**
* given a TableType object, make it into a tree using maps. * given a TableType object, make it into a tree using maps.
*
* @param table the table type to convert into a map * @param table the table type to convert into a map
* @return * @return
*/ */
private static Node tableToNode(TableType table, String name) { private static Node tableToNode(TableType table, String name) {
Node root = new Node(name); Node root = new Node("table", name, "Table");
Object[] rows = table.getRowKeys(); Object[] rows = table.getRowKeys();
Object[] cols = table.getColumnKeys(); Object[] cols = table.getColumnKeys();
// add the columns names
Node col_names = new Node("col_names", "col_names", "the column names, ~ seperated", false);
for (Object col : cols)
col_names.addChild(new Node("col", col.toString(), "a column name", false));
root.addChild(col_names);
for (int x = 0; x < table.getRowKeys().length; x++) { for (int x = 0; x < table.getRowKeys().length; x++) {
Node row = new Node(rows[x].toString()); Node row = new Node("row", rows[x].toString(), "a row");
root.addChild(row); root.addChild(row);
for (int y = 0; y < table.getRowKeys().length; y++) { for (int y = 0; y < table.getColumnKeys().length; y++) {
Node col = new Node(cols[y].toString()); Node col = new Node("column", cols[y].toString(), "a column");
row.addChild(col); row.addChild(col);
col.addChild(new Node(table.getCell(x,y))); col.addChild(new Node("cell(" + x + "," + y + ")", table.getCell(x, y), "a cell"));
} }
} }
return root; return root;
@ -64,6 +75,7 @@ public class ComplexDataUtils {
/** /**
* given a Collection object, make it into a tree using maps. * given a Collection object, make it into a tree using maps.
*
* @param coll the collection to iterate, and turn into a list * @param coll the collection to iterate, and turn into a list
* @return a mapping of String to Object * @return a mapping of String to Object
*/ */
@ -71,11 +83,10 @@ public class ComplexDataUtils {
Collection<Node> nodes = new ArrayList<Node>(); Collection<Node> nodes = new ArrayList<Node>();
Iterator<Object> iter = coll.iterator(); Iterator<Object> iter = coll.iterator();
for (int x = 0; x < coll.size(); x++) { for (int x = 0; x < coll.size(); x++) {
Node value = new Node(String.valueOf(x)); Node value = new Node("column " + x, String.valueOf(x), "column");
value.addChild(new Node(iter.next().toString())); value.addChild(new Node("value " + x, iter.next().toString(), "value"));
nodes.add(value); nodes.add(value);
} }
return nodes; return nodes;
} }
} }

View File

@ -7,12 +7,24 @@ import java.util.LinkedHashSet;
* a node, extracted using the new report output system. * a node, extracted using the new report output system.
*/ */
public class Node { public class Node {
public String value; public final String name;
public String description; // if one is available public final String value;
public final String description;
public final boolean display; // is this node an output node, or a node for tracking internal data? true if output node
public Collection<Node> children; public Collection<Node> children;
public Node(String value) { public Node(String name, String value, String description) {
this.value = value; this.value = value;
this.name = name;
this.description = description;
display = true;
}
public Node(String name, String value, String description, boolean display) {
this.value = value;
this.name = name;
this.description = description;
this.display = display;
} }
public void addChild(Node child) { public void addChild(Node child) {
@ -25,20 +37,27 @@ public class Node {
this.children.addAll(children); this.children.addAll(children);
} }
public Boolean getComplex() { return (children != null && children.size() > 0); } public Boolean getComplex() {
return (children != null && children.size() > 0);
}
/** /**
* a convenience method for adding a new sub-node with the specified value * a convenience method for adding a new sub-node with the specified value
*
* @param value the value of the sub-node * @param value the value of the sub-node
*/ */
public void createSubNode(String value) { public void createSubNode(String name, String value, String description) {
addChild(new Node(value)); addChild(new Node(name, value, description));
} }
public String getValue() { public String getValue() {
return value; return value;
} }
public String getName() {
return name;
}
public String getDescription() { public String getDescription() {
return description; return description;
} }
@ -46,4 +65,8 @@ public class Node {
public Collection<Node> getChildren() { public Collection<Node> getChildren() {
return children; return children;
} }
public boolean getDisplay() {
return display;
}
} }