From 0b43ee117cd06a138309a3d18be3b3809be87c9f Mon Sep 17 00:00:00 2001
From: Kiran V Garimella
Date: Mon, 25 Jul 2011 11:35:34 -0400
Subject: [PATCH 01/30] Added the required=false tag to the -noST and -noEV
arguments so the auto-help output doesn't look weird (i.e. listing arguments
as required when their value has already been specified by default).
---
.../sting/gatk/walkers/varianteval/VariantEvalWalker.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalWalker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalWalker.java
index fe3173506..3867aa958 100755
--- a/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalWalker.java
+++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/varianteval/VariantEvalWalker.java
@@ -67,7 +67,7 @@ public class VariantEvalWalker extends RodWalker implements Tr
@Argument(fullName="stratificationModule", shortName="ST", doc="One or more specific stratification modules to apply to the eval track(s) (in addition to the standard stratifications, unless -noS is specified)", required=false)
protected String[] STRATIFICATIONS_TO_USE = {};
- @Argument(fullName="doNotUseAllStandardStratifications", shortName="noST", doc="Do not use the standard stratification modules by default (instead, only those that are specified with the -S option)")
+ @Argument(fullName="doNotUseAllStandardStratifications", shortName="noST", doc="Do not use the standard stratification modules by default (instead, only those that are specified with the -S option)", required=false)
protected Boolean NO_STANDARD_STRATIFICATIONS = false;
@Argument(fullName="onlyVariantsOfType", shortName="VT", doc="If provided, only variants of these types will be considered during the evaluation, in ", required=false)
@@ -77,7 +77,7 @@ public class VariantEvalWalker extends RodWalker implements Tr
@Argument(fullName="evalModule", shortName="EV", doc="One or more specific eval modules to apply to the eval track(s) (in addition to the standard modules, unless -noE is specified)", required=false)
protected String[] MODULES_TO_USE = {};
- @Argument(fullName="doNotUseAllStandardModules", shortName="noEV", doc="Do not use the standard modules by default (instead, only those that are specified with the -E option)")
+ @Argument(fullName="doNotUseAllStandardModules", shortName="noEV", doc="Do not use the standard modules by default (instead, only those that are specified with the -E option)", required=false)
protected Boolean NO_STANDARD_MODULES = false;
// Other arguments
From 2ac490dbdf6710401566ab6930dd9169f559f8f7 Mon Sep 17 00:00:00 2001
From: Matt Hanna
Date: Mon, 25 Jul 2011 13:20:00 -0400
Subject: [PATCH 05/30] Fix improper detection of command-line arguments with
missing values.
---
.../commandline/ArgumentDefinitions.java | 3 +-
.../sting/commandline/ArgumentMatch.java | 2 +-
.../sting/commandline/ParsingEngine.java | 39 +++++++++++++++----
3 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/public/java/src/org/broadinstitute/sting/commandline/ArgumentDefinitions.java b/public/java/src/org/broadinstitute/sting/commandline/ArgumentDefinitions.java
index 9f92df6e0..8e3f753a8 100755
--- a/public/java/src/org/broadinstitute/sting/commandline/ArgumentDefinitions.java
+++ b/public/java/src/org/broadinstitute/sting/commandline/ArgumentDefinitions.java
@@ -174,7 +174,8 @@ public class ArgumentDefinitions implements Iterable {
static DefinitionMatcher VerifiableDefinitionMatcher = new DefinitionMatcher() {
public boolean matches( ArgumentDefinition definition, Object key ) {
- return definition.validation != null;
+ // We can perform some sort of validation for anything that isn't a flag.
+ return !definition.isFlag;
}
};
}
diff --git a/public/java/src/org/broadinstitute/sting/commandline/ArgumentMatch.java b/public/java/src/org/broadinstitute/sting/commandline/ArgumentMatch.java
index 60ed8c899..351583c07 100755
--- a/public/java/src/org/broadinstitute/sting/commandline/ArgumentMatch.java
+++ b/public/java/src/org/broadinstitute/sting/commandline/ArgumentMatch.java
@@ -44,7 +44,7 @@ public class ArgumentMatch implements Iterable {
public final String label;
/**
- * Maps indicies of command line arguments to values paired with that argument.
+ * Maps indices of command line arguments to values paired with that argument.
*/
public final SortedMap> indices = new TreeMap>();
diff --git a/public/java/src/org/broadinstitute/sting/commandline/ParsingEngine.java b/public/java/src/org/broadinstitute/sting/commandline/ParsingEngine.java
index 8423bb2f2..279aed396 100755
--- a/public/java/src/org/broadinstitute/sting/commandline/ParsingEngine.java
+++ b/public/java/src/org/broadinstitute/sting/commandline/ParsingEngine.java
@@ -41,6 +41,11 @@ import java.util.*;
* A parser for Sting command-line arguments.
*/
public class ParsingEngine {
+ /**
+ * The loaded argument sources along with their back definitions.
+ */
+ private Map argumentSourcesByDefinition = new HashMap();
+
/**
* A list of defined arguments against which command lines are matched.
* Package protected for testing access.
@@ -107,8 +112,13 @@ public class ParsingEngine {
*/
public void addArgumentSource( String sourceName, Class sourceClass ) {
List argumentsFromSource = new ArrayList();
- for( ArgumentSource argumentSource: extractArgumentSources(sourceClass) )
- argumentsFromSource.addAll( argumentSource.createArgumentDefinitions() );
+ for( ArgumentSource argumentSource: extractArgumentSources(sourceClass) ) {
+ List argumentDefinitions = argumentSource.createArgumentDefinitions();
+ for(ArgumentDefinition argumentDefinition: argumentDefinitions) {
+ argumentSourcesByDefinition.put(argumentDefinition,argumentSource);
+ argumentsFromSource.add( argumentDefinition );
+ }
+ }
argumentDefinitions.add( new ArgumentDefinitionGroup(sourceName, argumentsFromSource) );
}
@@ -199,16 +209,25 @@ public class ParsingEngine {
throw new InvalidArgumentException( invalidArguments );
}
- // Find invalid argument values (arguments that fail the regexp test.
+ // Find invalid argument values -- invalid arguments are either completely missing or fail the specified 'validation' regular expression.
if( !skipValidationOf.contains(ValidationType.InvalidArgumentValue) ) {
Collection verifiableArguments =
argumentDefinitions.findArgumentDefinitions( null, ArgumentDefinitions.VerifiableDefinitionMatcher );
Collection> invalidValues = new ArrayList>();
for( ArgumentDefinition verifiableArgument: verifiableArguments ) {
ArgumentMatches verifiableMatches = argumentMatches.findMatches( verifiableArgument );
+ // Check to see whether an argument value was specified. Argument values must be provided
+ // when the argument name is specified and the argument is not a flag type.
+ for(ArgumentMatch verifiableMatch: verifiableMatches) {
+ ArgumentSource argumentSource = argumentSourcesByDefinition.get(verifiableArgument);
+ if(verifiableMatch.values().size() == 0 && !verifiableArgument.isFlag && argumentSource.createsTypeDefault())
+ invalidValues.add(new Pair(verifiableArgument,null));
+ }
+
+ // Ensure that the field contents meet the validation criteria specified by the regular expression.
for( ArgumentMatch verifiableMatch: verifiableMatches ) {
for( String value: verifiableMatch.values() ) {
- if( !value.matches(verifiableArgument.validation) )
+ if( verifiableArgument.validation != null && !value.matches(verifiableArgument.validation) )
invalidValues.add( new Pair(verifiableArgument, value) );
}
}
@@ -515,10 +534,14 @@ class InvalidArgumentValueException extends ArgumentException {
private static String formatArguments( Collection> invalidArgumentValues ) {
StringBuilder sb = new StringBuilder();
for( Pair invalidValue: invalidArgumentValues ) {
- sb.append( String.format("%nArgument '--%s' has value of incorrect format: %s (should match %s)",
- invalidValue.first.fullName,
- invalidValue.second,
- invalidValue.first.validation) );
+ if(invalidValue.getSecond() == null)
+ sb.append( String.format("%nArgument '--%s' requires a value but none was provided",
+ invalidValue.first.fullName) );
+ else
+ sb.append( String.format("%nArgument '--%s' has value of incorrect format: %s (should match %s)",
+ invalidValue.first.fullName,
+ invalidValue.second,
+ invalidValue.first.validation) );
}
return sb.toString();
}
From 6f43284053cbae9e263ac43056b6c4445fc19017 Mon Sep 17 00:00:00 2001
From: Matt Hanna
Date: Mon, 25 Jul 2011 15:19:41 -0400
Subject: [PATCH 09/30] Switch to including our entire exception tree rather
than just UserException.
---
build.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/build.xml b/build.xml
index 295cd95e1..a9348eae3 100644
--- a/build.xml
+++ b/build.xml
@@ -489,7 +489,7 @@
-
+
From fec495e2928a2dc13e5957ab1f3131b151b18a08 Mon Sep 17 00:00:00 2001
From: Matt Hanna
Date: Tue, 26 Jul 2011 15:43:20 -0400
Subject: [PATCH 19/30] Fix a nasty little bug in the sharding system: if the
last shard in contig n overlaps exactly on disk with the first shard in
contig n+1, the shards would be merged together to avoid duplicate
extraction. Unfortunately, the interval overlap filter couldn't handle
shards spanning contigs, and was choosing to filter out reads from contig n+1
which should have been included. I'm not completely sure why the BAM indexing
code would ever specify that the end of one chromosome had the same on-disk
location as the start of the next one. I suspect that this is a indexer
performance bug.
---
.../gatk/datasources/reads/SAMDataSource.java | 45 ++++++++++++++++---
1 file changed, 39 insertions(+), 6 deletions(-)
diff --git a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/SAMDataSource.java b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/SAMDataSource.java
index 6064806f3..572970349 100755
--- a/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/SAMDataSource.java
+++ b/public/java/src/org/broadinstitute/sting/gatk/datasources/reads/SAMDataSource.java
@@ -893,6 +893,7 @@ public class SAMDataSource {
* Custom representation of interval bounds.
* Makes it simpler to track current position.
*/
+ private int[] intervalContigIndices;
private int[] intervalStarts;
private int[] intervalEnds;
@@ -917,12 +918,14 @@ public class SAMDataSource {
if(foundMappedIntervals) {
if(keepOnlyUnmappedReads)
throw new ReviewedStingException("Tried to apply IntervalOverlapFilteringIterator to a mixed of mapped and unmapped intervals. Please apply this filter to only mapped or only unmapped reads");
+ this.intervalContigIndices = new int[intervals.size()];
this.intervalStarts = new int[intervals.size()];
this.intervalEnds = new int[intervals.size()];
int i = 0;
for(GenomeLoc interval: intervals) {
- intervalStarts[i] = (int)interval.getStart();
- intervalEnds[i] = (int)interval.getStop();
+ intervalContigIndices[i] = interval.getContigIndex();
+ intervalStarts[i] = interval.getStart();
+ intervalEnds[i] = interval.getStop();
i++;
}
}
@@ -961,11 +964,10 @@ public class SAMDataSource {
while(nextRead == null && (keepOnlyUnmappedReads || currentBound < intervalStarts.length)) {
if(!keepOnlyUnmappedReads) {
// Mapped read filter; check against GenomeLoc-derived bounds.
- if(candidateRead.getAlignmentEnd() >= intervalStarts[currentBound] ||
- (candidateRead.getReadUnmappedFlag() && candidateRead.getAlignmentStart() >= intervalStarts[currentBound])) {
- // This read ends after the current interval begins (or, if unmapped, starts within the bounds of the interval.
+ if(readEndsOnOrAfterStartingBound(candidateRead)) {
+ // This read ends after the current interval begins.
// Promising, but this read must be checked against the ending bound.
- if(candidateRead.getAlignmentStart() <= intervalEnds[currentBound]) {
+ if(readStartsOnOrBeforeEndingBound(candidateRead)) {
// Yes, this read is within both bounds. This must be our next read.
nextRead = candidateRead;
break;
@@ -993,6 +995,37 @@ public class SAMDataSource {
candidateRead = iterator.next();
}
}
+
+ /**
+ * Check whether the read lies after the start of the current bound. If the read is unmapped but placed, its
+ * end will be distorted, so rely only on the alignment start.
+ * @param read The read to position-check.
+ * @return True if the read starts after the current bounds. False otherwise.
+ */
+ private boolean readEndsOnOrAfterStartingBound(final SAMRecord read) {
+ return
+ // Read ends on a later contig, or...
+ read.getReferenceIndex() > intervalContigIndices[currentBound] ||
+ // Read ends of this contig...
+ (read.getReferenceIndex() == intervalContigIndices[currentBound] &&
+ // either after this location, or...
+ (read.getAlignmentEnd() >= intervalStarts[currentBound] ||
+ // read is unmapped but positioned and alignment start is on or after this start point.
+ (read.getReadUnmappedFlag() && read.getAlignmentStart() >= intervalStarts[currentBound])));
+ }
+
+ /**
+ * Check whether the read lies before the end of the current bound.
+ * @param read The read to position-check.
+ * @return True if the read starts after the current bounds. False otherwise.
+ */
+ private boolean readStartsOnOrBeforeEndingBound(final SAMRecord read) {
+ return
+ // Read starts on a prior contig, or...
+ read.getReferenceIndex() < intervalContigIndices[currentBound] ||
+ // Read starts on this contig and the alignment start is registered before this end point.
+ (read.getReferenceIndex() == intervalContigIndices[currentBound] && read.getAlignmentStart() <= intervalEnds[currentBound]);
+ }
}
/**
From f6a5e0e36aedad122f456db3b0dadfdde4c18e12 Mon Sep 17 00:00:00 2001
From: Mark DePristo
Date: Tue, 26 Jul 2011 17:35:30 -0400
Subject: [PATCH 21/30] Go for global integrationtest path first, if possible.
---
public/java/test/org/broadinstitute/sting/MD5DB.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/public/java/test/org/broadinstitute/sting/MD5DB.java b/public/java/test/org/broadinstitute/sting/MD5DB.java
index 6f56fce4b..0194e114a 100644
--- a/public/java/test/org/broadinstitute/sting/MD5DB.java
+++ b/public/java/test/org/broadinstitute/sting/MD5DB.java
@@ -79,8 +79,8 @@ public class MD5DB {
* @return
*/
public static String getMD5FilePath(final String md5, final String valueIfNotFound) {
- // we prefer the local db to the global DB, so match it first
- for ( String dir : Arrays.asList(LOCAL_MD5_DB_DIR, GLOBAL_MD5_DB_DIR)) {
+ // we prefer the global db to the local DB, so match it first
+ for ( String dir : Arrays.asList(GLOBAL_MD5_DB_DIR, LOCAL_MD5_DB_DIR)) {
File f = getFileForMD5(md5, dir);
if ( f.exists() && f.canRead() )
return f.getPath();
From 412c466de6cee301082086cb0e99dc193029faff Mon Sep 17 00:00:00 2001
From: Kiran V Garimella
Date: Tue, 26 Jul 2011 17:43:43 -0400
Subject: [PATCH 22/30] Bug fix, wherein triple-hets after genotype refinement
need to be left unphased, not just prior to refinement
---
.../gatk/walkers/phasing/PhaseByTransmission.java | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/phasing/PhaseByTransmission.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/phasing/PhaseByTransmission.java
index d3ed46ce8..cf4afbb6d 100755
--- a/public/java/src/org/broadinstitute/sting/gatk/walkers/phasing/PhaseByTransmission.java
+++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/phasing/PhaseByTransmission.java
@@ -234,7 +234,7 @@ public class PhaseByTransmission extends RodWalker {
finalGenotypes.add(father);
finalGenotypes.add(child);
- if (mother.isCalled() && father.isCalled() && child.isCalled() && !(mother.isHet() && father.isHet() && child.isHet())) {
+ if (mother.isCalled() && father.isCalled() && child.isCalled()) {
ArrayList possibleMotherGenotypes = createAllThreeGenotypes(ref, alt, mother);
ArrayList possibleFatherGenotypes = createAllThreeGenotypes(ref, alt, father);
ArrayList possibleChildGenotypes = createAllThreeGenotypes(ref, alt, child);
@@ -265,12 +265,14 @@ public class PhaseByTransmission extends RodWalker {
}
}
- Map attributes = new HashMap();
- attributes.putAll(bestChildGenotype.getAttributes());
- attributes.put(TRANSMISSION_PROBABILITY_TAG_NAME, bestPrior*bestConfigurationLikelihood / norm);
- bestChildGenotype = Genotype.modifyAttributes(bestChildGenotype, attributes);
+ if (!(bestMotherGenotype.isHet() && bestFatherGenotype.isHet() && bestChildGenotype.isHet())) {
+ Map attributes = new HashMap();
+ attributes.putAll(bestChildGenotype.getAttributes());
+ attributes.put(TRANSMISSION_PROBABILITY_TAG_NAME, bestPrior*bestConfigurationLikelihood / norm);
+ bestChildGenotype = Genotype.modifyAttributes(bestChildGenotype, attributes);
- finalGenotypes = getPhasedGenotypes(bestMotherGenotype, bestFatherGenotype, bestChildGenotype);
+ finalGenotypes = getPhasedGenotypes(bestMotherGenotype, bestFatherGenotype, bestChildGenotype);
+ }
}
return finalGenotypes;
From 92a11ed8dcc6899697196e329ea2b3d944fb3bf2 Mon Sep 17 00:00:00 2001
From: Kiran V Garimella
Date: Tue, 26 Jul 2011 17:52:25 -0400
Subject: [PATCH 23/30] Updated MD5 for PhaseByTransmissionIntegrationTest
---
.../walkers/phasing/PhaseByTransmissionIntegrationTest.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/public/java/test/org/broadinstitute/sting/gatk/walkers/phasing/PhaseByTransmissionIntegrationTest.java b/public/java/test/org/broadinstitute/sting/gatk/walkers/phasing/PhaseByTransmissionIntegrationTest.java
index 69f98b700..f62f12082 100644
--- a/public/java/test/org/broadinstitute/sting/gatk/walkers/phasing/PhaseByTransmissionIntegrationTest.java
+++ b/public/java/test/org/broadinstitute/sting/gatk/walkers/phasing/PhaseByTransmissionIntegrationTest.java
@@ -20,7 +20,7 @@ public class PhaseByTransmissionIntegrationTest extends WalkerTest {
"-o %s"
),
1,
- Arrays.asList("ff02b1583ee3a12ed66a9c0e08e346b2")
+ Arrays.asList("45fef0e23113e2fcd9570379e2fc1b75")
);
executeTest("testBasicFunctionality", spec);
}
From 321afac4e8ebc3a6db2c0e9b00094f0dfe12f0e6 Mon Sep 17 00:00:00 2001
From: Mauricio Carneiro
Date: Tue, 26 Jul 2011 19:29:25 -0400
Subject: [PATCH 24/30] Updates to the help layout.
*New style.css, new template for the walker auto-generated html. Short description is no longer repeated in the long description of the walker.
*Updated DiffObjectsWalker and ContigStatsWalker as "reference" documented walkers.
---
.../walkers/diffengine/DiffObjectsWalker.java | 74 +++++++++++--------
.../help/GenericDocumentationHandler.java | 2 +-
settings/helpTemplates/common.html | 6 +-
settings/helpTemplates/generic.template.html | 7 +-
settings/helpTemplates/style.css | 52 +++++++++++--
5 files changed, 96 insertions(+), 45 deletions(-)
diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/DiffObjectsWalker.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/DiffObjectsWalker.java
index b679f967a..f43d1342d 100644
--- a/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/DiffObjectsWalker.java
+++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/DiffObjectsWalker.java
@@ -25,7 +25,6 @@
package org.broadinstitute.sting.gatk.walkers.diffengine;
import org.broadinstitute.sting.commandline.Argument;
-import org.broadinstitute.sting.commandline.Hidden;
import org.broadinstitute.sting.commandline.Output;
import org.broadinstitute.sting.gatk.contexts.AlignmentContext;
import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
@@ -35,34 +34,45 @@ import org.broadinstitute.sting.gatk.walkers.RodWalker;
import java.io.File;
import java.io.PrintStream;
-import java.util.Arrays;
import java.util.List;
/**
* A generic engine for comparing tree-structured objects
+ *
*
- * Compares two record-oriented files, itemizing specific difference between equivalent
- * records in the two files. Reports both itemized and summarized differences.
- *
- * What are the summarized differences and the DiffObjectsWalker
+ * Compares two record-oriented files, itemizing specific difference between equivalent
+ * records in the two files. Reports both itemized and summarized differences.
+ *
+ *
+ * What are the summarized differences and the DiffObjectsWalker?
+ *
*
* The GATK contains a summarizing difference engine that compares hierarchical data structures to emit:
- *
- * - A list of specific differences between the two data structures. This is similar to saying the value in field A in record 1 in file F differences from the value in field A in record 1 in file G.
- *
- A summarized list of differences ordered by frequency of the difference. This output is similar to saying field A in 50 records in files F and G differed.
- *
+ *
+ * - A list of specific differences between the two data structures. This is similar to saying the value in field A in record 1 in file F differences from the value in field A in record 1 in file G.
+ *
- A summarized list of differences ordered by frequency of the difference. This output is similar to saying field A in 50 records in files F and G differed.
+ *
+ *
*
*
- * The GATK contains a private walker DiffObjects that allows you access to the DiffEngine capabilities on the command line. Simply provide the walker with the master and test files and it will emit summarized differences for you.
+ * The GATK contains a private walker DiffObjects that allows you access to the DiffEngine capabilities on the command line. Simply provide the walker with the master and test files and it will emit summarized differences for you.
+ *
+ *
+ * Why?
*
*
- * Why?
- *
- * The reason for this system is that it allows you to compare two structured files -- such as BAMs and VCFs -- for common differences among them. This is primarily useful in regression testing or optimization, where you want to ensure that the differences are those that you expect and not any others.
+ * The reason for this system is that it allows you to compare two structured files -- such as BAMs and VCFs -- for common differences among them. This is primarily useful in regression testing or optimization, where you want to ensure that the differences are those that you expect and not any others.
+ *
*
- * Understanding the output
- *
The DiffEngine system compares to two hierarchical data structures for specific differences in the values of named
- * nodes. Suppose I have two trees:
+ *
Input
+ *
+ * The DiffObjectsWalker works with BAM or VCF files.
+ *
+ *
+ * Output
+ *
+ * The DiffEngine system compares to two hierarchical data structures for specific differences in the values of named
+ * nodes. Suppose I have two trees:
*
* Tree1=(A=1 B=(C=2 D=3))
* Tree2=(A=1 B=(C=3 D=3 E=4))
@@ -70,33 +80,37 @@ import java.util.List;
*
*
* where every node in the tree is named, or is a raw value (here all leaf values are integers). The DiffEngine
- * traverses these data structures by name, identifies equivalent nodes by fully qualified names
- * (Tree1.A is distinct from Tree2.A, and determines where their values are equal (Tree1.A=1, Tree2.A=1, so they are).
- * These itemized differences are listed as:
+ * traverses these data structures by name, identifies equivalent nodes by fully qualified names
+ * (Tree1.A is distinct from Tree2.A, and determines where their values are equal (Tree1.A=1, Tree2.A=1, so they are).
+ * These itemized differences are listed as:
*
* Tree1.B.C=2 != Tree2.B.C=3
* Tree1.B.C=2 != Tree3.B.C=4
* Tree2.B.C=3 != Tree3.B.C=4
* Tree1.B.E=MISSING != Tree2.B.E=4
*
+ *
*
- * This conceptually very similar to the output of the unix command line tool diff. What's nice about DiffEngine though
- * is that it computes similarity among the itemized differences and displays the count of differences names
- * in the system. In the above example, the field C is not equal three times, while the missing E in Tree1 occurs
- * only once. So the summary is:
+ * This conceptually very similar to the output of the unix command line tool diff. What's nice about DiffEngine though
+ * is that it computes similarity among the itemized differences and displays the count of differences names
+ * in the system. In the above example, the field C is not equal three times, while the missing E in Tree1 occurs
+ * only once. So the summary is:
*
*
* *.B.C : 3
* *.B.E : 1
*
- * where the * operator indicates that any named field matches. This output is sorted by counts, and provides an
- * immediate picture of the commonly occurring differences among the files.
+ *
*
- * Below is a detailed example of two VCF fields that differ because of a bug in the AC, AF, and AN counting routines,
- * detected by the integrationtest integration (more below). You can see that in the although there are many specific
- * instances of these differences between the two files, the summarized differences provide an immediate picture that
- * the AC, AF, and AN fields are the major causes of the differences.
+ * where the * operator indicates that any named field matches. This output is sorted by counts, and provides an
+ * immediate picture of the commonly occurring differences among the files.
*
+ * Below is a detailed example of two VCF fields that differ because of a bug in the AC, AF, and AN counting routines,
+ * detected by the integrationtest integration (more below). You can see that in the although there are many specific
+ * instances of these differences between the two files, the summarized differences provide an immediate picture that
+ * the AC, AF, and AN fields are the major causes of the differences.
+ *
+ *
*
[testng] path count
[testng] *.*.*.AC 6
diff --git a/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java b/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java
index fd1048844..c69345816 100644
--- a/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java
+++ b/public/java/src/org/broadinstitute/sting/utils/help/GenericDocumentationHandler.java
@@ -92,7 +92,7 @@ public class GenericDocumentationHandler extends DocumentedGATKFeatureHandler {
for(Tag tag: classdoc.firstSentenceTags())
summaryBuilder.append(tag.text());
root.put("summary", summaryBuilder.toString());
- root.put("description", classdoc.commentText());
+ root.put("description", classdoc.commentText().substring(summaryBuilder.toString().length()));
root.put("timestamp", toProcess.buildTimestamp);
root.put("version", toProcess.absoluteVersion);
diff --git a/settings/helpTemplates/common.html b/settings/helpTemplates/common.html
index ebc060d0a..1554a1d40 100644
--- a/settings/helpTemplates/common.html
+++ b/settings/helpTemplates/common.html
@@ -6,10 +6,10 @@
#macro>
<#macro headerInfo>
+#macro>
+
+<#macro footerInfo>
See also Main index | GATK wiki | GATK support forum
GATK version ${version} built at ${timestamp}.
#macro>
-<#macro footerInfo>
-#macro>
-
diff --git a/settings/helpTemplates/generic.template.html b/settings/helpTemplates/generic.template.html
index ca0d1e76f..032407164 100644
--- a/settings/helpTemplates/generic.template.html
+++ b/settings/helpTemplates/generic.template.html
@@ -53,19 +53,18 @@
${name}
<@headerInfo />
- Brief summary
- ${summary}
+ ${summary}
<#if author??>
Author
${author}
#if>
- Detailed description
+ Introduction
${description}
<#-- Create the argument summary -->
<#if arguments.all?size != 0>
- Feature specific arguments
+ ${name} specific arguments
diff --git a/settings/helpTemplates/style.css b/settings/helpTemplates/style.css
index 79f409f55..1d7bcc576 100644
--- a/settings/helpTemplates/style.css
+++ b/settings/helpTemplates/style.css
@@ -14,29 +14,67 @@ p, ul, ol, dl, dt, dd, td
font-size: 12pt;
}
-p.version, p.see-also
+p
{
- font-size: 8pt;
+ margin-left: 1em;
}
-h1, h2, h3
+p.summary
+{
+ margin-left: 2em;
+ margin-top: -20pt;
+ font-style: italic;
+}
+
+p.see-also
+{
+ font-size: 10pt;
+ margin-left: 0em;
+ margin-top: 3em;
+ text-align: center;
+}
+
+p.version
+{
+ font-size: 8pt;
+ margin-left: 0em;
+ margin-top: -8pt;
+ text-align: center;
+}
+
+
+h1, h2, h3, h4
{
font-family: Corbel, Arial, Helvetica, Sans-Serif;
font-weight: bold;
text-align: left;
- color: #669;
}
h1
{
font-size: 32pt;
letter-spacing: -2px;
+ color: #669;
}
-h3
+h2
{
- font-size: 16pt;
- font-weight: normal;
+ font-size: 16pt;
+ font-weight: bold;
+ margin-top: 2em;
+ color: #669;
+}
+
+h3
+{
+ font-size: 12pt;
+ margin-left: 1em;
+ color: #000;
+}
+
+hr
+{
+ margin-top: 4em;
}
/*
From dc8061e7a69b81715ac3ba967e34dd23026a8e6d Mon Sep 17 00:00:00 2001
From: Kiran V Garimella
Date: Wed, 27 Jul 2011 10:34:56 -0400
Subject: [PATCH 26/30] Moved gsalib from private/ to public/
---
build.xml | 2 +-
public/R/src/gsalib/DESCRIPTION | 10 ++
public/R/src/gsalib/R/gsa.error.R | 12 ++
public/R/src/gsalib/R/gsa.getargs.R | 116 ++++++++++++++++++
public/R/src/gsalib/R/gsa.message.R | 3 +
public/R/src/gsalib/R/gsa.plot.venn.R | 50 ++++++++
public/R/src/gsalib/R/gsa.read.eval.R | 83 +++++++++++++
public/R/src/gsalib/R/gsa.read.gatkreport.R | 64 ++++++++++
public/R/src/gsalib/R/gsa.read.squidmetrics.R | 28 +++++
public/R/src/gsalib/R/gsa.read.vcf.R | 23 ++++
public/R/src/gsalib/R/gsa.warn.R | 3 +
public/R/src/gsalib/Read-and-delete-me | 9 ++
public/R/src/gsalib/data/tearsheetdrop.jpg | Bin 0 -> 50343 bytes
public/R/src/gsalib/man/gsa.error.Rd | 49 ++++++++
public/R/src/gsalib/man/gsa.getargs.Rd | 57 +++++++++
public/R/src/gsalib/man/gsa.message.Rd | 44 +++++++
public/R/src/gsalib/man/gsa.plot.venn.Rd | 75 +++++++++++
public/R/src/gsalib/man/gsa.read.eval.Rd | 111 +++++++++++++++++
.../R/src/gsalib/man/gsa.read.gatkreport.Rd | 55 +++++++++
.../R/src/gsalib/man/gsa.read.squidmetrics.Rd | 48 ++++++++
public/R/src/gsalib/man/gsa.read.vcf.Rd | 53 ++++++++
public/R/src/gsalib/man/gsa.warn.Rd | 46 +++++++
public/R/src/gsalib/man/gsalib-package.Rd | 68 ++++++++++
23 files changed, 1008 insertions(+), 1 deletion(-)
create mode 100644 public/R/src/gsalib/DESCRIPTION
create mode 100644 public/R/src/gsalib/R/gsa.error.R
create mode 100644 public/R/src/gsalib/R/gsa.getargs.R
create mode 100644 public/R/src/gsalib/R/gsa.message.R
create mode 100644 public/R/src/gsalib/R/gsa.plot.venn.R
create mode 100644 public/R/src/gsalib/R/gsa.read.eval.R
create mode 100644 public/R/src/gsalib/R/gsa.read.gatkreport.R
create mode 100644 public/R/src/gsalib/R/gsa.read.squidmetrics.R
create mode 100644 public/R/src/gsalib/R/gsa.read.vcf.R
create mode 100644 public/R/src/gsalib/R/gsa.warn.R
create mode 100644 public/R/src/gsalib/Read-and-delete-me
create mode 100755 public/R/src/gsalib/data/tearsheetdrop.jpg
create mode 100644 public/R/src/gsalib/man/gsa.error.Rd
create mode 100644 public/R/src/gsalib/man/gsa.getargs.Rd
create mode 100644 public/R/src/gsalib/man/gsa.message.Rd
create mode 100644 public/R/src/gsalib/man/gsa.plot.venn.Rd
create mode 100644 public/R/src/gsalib/man/gsa.read.eval.Rd
create mode 100644 public/R/src/gsalib/man/gsa.read.gatkreport.Rd
create mode 100644 public/R/src/gsalib/man/gsa.read.squidmetrics.Rd
create mode 100644 public/R/src/gsalib/man/gsa.read.vcf.Rd
create mode 100644 public/R/src/gsalib/man/gsa.warn.Rd
create mode 100644 public/R/src/gsalib/man/gsalib-package.Rd
diff --git a/build.xml b/build.xml
index 60c678591..438e9c90c 100644
--- a/build.xml
+++ b/build.xml
@@ -1089,7 +1089,7 @@
-
+
diff --git a/public/R/src/gsalib/DESCRIPTION b/public/R/src/gsalib/DESCRIPTION
new file mode 100644
index 000000000..6116e8c66
--- /dev/null
+++ b/public/R/src/gsalib/DESCRIPTION
@@ -0,0 +1,10 @@
+Package: gsalib
+Type: Package
+Title: Utility functions
+Version: 1.0
+Date: 2010-10-02
+Author: Kiran Garimella
+Maintainer: Kiran Garimella
+Description: Utility functions for GATK NGS analyses
+License: BSD
+LazyLoad: yes
diff --git a/public/R/src/gsalib/R/gsa.error.R b/public/R/src/gsalib/R/gsa.error.R
new file mode 100644
index 000000000..1c6a56046
--- /dev/null
+++ b/public/R/src/gsalib/R/gsa.error.R
@@ -0,0 +1,12 @@
+gsa.error <- function(message) {
+ message("");
+ gsa.message("Error: **********");
+ gsa.message(sprintf("Error: %s", message));
+ gsa.message("Error: **********");
+ message("");
+
+ traceback();
+
+ message("");
+ stop(message, call. = FALSE);
+}
diff --git a/public/R/src/gsalib/R/gsa.getargs.R b/public/R/src/gsalib/R/gsa.getargs.R
new file mode 100644
index 000000000..94613bf93
--- /dev/null
+++ b/public/R/src/gsalib/R/gsa.getargs.R
@@ -0,0 +1,116 @@
+.gsa.getargs.usage <- function(argspec, doc) {
+ cargs = commandArgs();
+
+ usage = "Usage:";
+
+ fileIndex = grep("--file=", cargs);
+ if (length(fileIndex) > 0) {
+ progname = gsub("--file=", "", cargs[fileIndex[1]]);
+
+ usage = sprintf("Usage: Rscript %s [arguments]", progname);
+
+ if (!is.na(doc)) {
+ message(sprintf("%s: %s\n", progname, doc));
+ }
+ }
+
+ message(usage);
+
+ for (argname in names(argspec)) {
+ key = argname;
+ defaultValue = 0;
+ doc = "";
+
+ if (is.list(argspec[[argname]])) {
+ defaultValue = argspec[[argname]]$value;
+ doc = argspec[[argname]]$doc;
+ }
+
+ message(sprintf(" -%-10s\t[default: %s]\t%s", key, defaultValue, doc));
+ }
+
+ message("");
+
+ stop(call. = FALSE);
+}
+
+gsa.getargs <- function(argspec, doc = NA) {
+ argsenv = new.env();
+
+ for (argname in names(argspec)) {
+ value = 0;
+ if (is.list(argspec[[argname]])) {
+ value = argspec[[argname]]$value;
+ } else {
+ value = argspec[[argname]];
+ }
+
+ assign(argname, value, envir=argsenv);
+ }
+
+ if (interactive()) {
+ for (argname in names(argspec)) {
+ value = get(argname, envir=argsenv);
+
+ if (is.na(value) | is.null(value)) {
+ if (exists("cmdargs")) {
+ assign(argname, cmdargs[[argname]], envir=argsenv);
+ } else {
+ assign(argname, readline(sprintf("Please enter a value for '%s': ", argname)), envir=argsenv);
+ }
+ } else {
+ assign(argname, value, envir=argsenv);
+ }
+ }
+ } else {
+ cargs = commandArgs(TRUE);
+
+ if (length(cargs) == 0) {
+ .gsa.getargs.usage(argspec, doc);
+ }
+
+ for (i in 1:length(cargs)) {
+ if (length(grep("^-", cargs[i], ignore.case=TRUE)) > 0) {
+ key = gsub("-", "", cargs[i]);
+ value = cargs[i+1];
+
+ if (key == "h" | key == "help") {
+ .gsa.getargs.usage(argspec, doc);
+ }
+
+ if (length(grep("^[\\d\\.e\\+\\-]+$", value, perl=TRUE, ignore.case=TRUE)) > 0) {
+ value = as.numeric(value);
+ }
+
+ assign(key, value, envir=argsenv);
+ }
+ }
+ }
+
+ args = as.list(argsenv);
+
+ isMissingArgs = 0;
+ missingArgs = c();
+
+ for (arg in names(argspec)) {
+ if (is.na(args[[arg]]) | is.null(args[[arg]])) {
+ gsa.warn(sprintf("Value for required argument '-%s' was not specified", arg));
+
+ isMissingArgs = 1;
+ missingArgs = c(missingArgs, arg);
+ }
+ }
+
+ if (isMissingArgs) {
+ gsa.error(
+ paste(
+ "Missing required arguments: -",
+ paste(missingArgs, collapse=" -"),
+ ". Specify -h or -help to this script for a list of available arguments.",
+ sep=""
+ )
+ );
+ }
+
+ args;
+}
diff --git a/public/R/src/gsalib/R/gsa.message.R b/public/R/src/gsalib/R/gsa.message.R
new file mode 100644
index 000000000..a2b909d3d
--- /dev/null
+++ b/public/R/src/gsalib/R/gsa.message.R
@@ -0,0 +1,3 @@
+gsa.message <- function(message) {
+ message(sprintf("[gsalib] %s", message));
+}
diff --git a/public/R/src/gsalib/R/gsa.plot.venn.R b/public/R/src/gsalib/R/gsa.plot.venn.R
new file mode 100644
index 000000000..b1353ccc1
--- /dev/null
+++ b/public/R/src/gsalib/R/gsa.plot.venn.R
@@ -0,0 +1,50 @@
+gsa.plot.venn <-
+function(a, b, c=0, a_and_b, a_and_c=0, b_and_c=0,
+ col=c("#FF6342", "#63C6DE", "#ADDE63"),
+ pos=c(0.20, 0.20, 0.80, 0.82),
+ debug=0
+ ) {
+ library(png);
+ library(graphics);
+
+ # Set up properties
+ for (i in 1:length(col)) {
+ rgbcol = col2rgb(col[i]);
+ col[i] = sprintf("%02X%02X%02X", rgbcol[1], rgbcol[2], rgbcol[3]);
+ }
+
+ chco = paste(col[1], col[2], col[3], sep=",");
+ chd = paste(a, b, c, a_and_b, a_and_c, b_and_c, sep=",");
+
+ props = c(
+ 'cht=v',
+ 'chs=525x525',
+ 'chds=0,10000000000',
+ paste('chco=', chco, sep=""),
+ paste('chd=t:', chd, sep="")
+ );
+ proplist = paste(props[1], props[2], props[3], props[4], props[5], sep='&');
+
+ # Get the venn diagram (as a temporary file)
+ filename = tempfile("venn");
+ cmd = paste("wget -O ", filename, " 'http://chart.apis.google.com/chart?", proplist, "' > /dev/null 2>&1", sep="");
+
+ if (debug == 1) {
+ print(cmd);
+ }
+ system(cmd);
+
+ # Render the temp png file into a plotting frame
+ a = readPNG(filename);
+
+ plot(0, 0, type="n", xaxt="n", yaxt="n", bty="n", xlim=c(0, 1), ylim=c(0, 1), xlab="", ylab="");
+ if (c == 0 || a >= b) {
+ rasterImage(a, pos[1], pos[2], pos[3], pos[4]);
+ } else {
+ rasterImage(a, 0.37+pos[1], 0.37+pos[2], 0.37+pos[3], 0.37+pos[4], angle=180);
+ }
+
+ # Clean up!
+ unlink(filename);
+}
+
diff --git a/public/R/src/gsalib/R/gsa.read.eval.R b/public/R/src/gsalib/R/gsa.read.eval.R
new file mode 100644
index 000000000..f1d49092b
--- /dev/null
+++ b/public/R/src/gsalib/R/gsa.read.eval.R
@@ -0,0 +1,83 @@
+.gsa.attemptToLoadFile <- function(filename) {
+ file = NA;
+
+ if (file.exists(filename) & file.info(filename)$size > 500) {
+ file = read.csv(filename, header=TRUE, comment.char="#");
+ }
+
+ file;
+}
+
+gsa.read.eval <-
+function(evalRoot) {
+ fileAlleleCountStats = paste(evalRoot, ".AlleleCountStats.csv", sep="");
+ fileCompOverlap = paste(evalRoot, ".Comp_Overlap.csv", sep="");
+ fileCountVariants = paste(evalRoot, ".Count_Variants.csv", sep="");
+ fileGenotypeConcordance = paste(evalRoot, ".Genotype_Concordance.csv", sep="");
+ fileMetricsByAc = paste(evalRoot, ".MetricsByAc.csv", sep="");
+ fileMetricsBySample = paste(evalRoot, ".MetricsBySample.csv", sep="");
+ fileQuality_Metrics_by_allele_count = paste(evalRoot, ".Quality_Metrics_by_allele_count.csv", sep="");
+ fileQualityScoreHistogram = paste(evalRoot, ".QualityScoreHistogram.csv", sep="");
+ fileSampleStatistics = paste(evalRoot, ".Sample_Statistics.csv", sep="");
+ fileSampleSummaryStatistics = paste(evalRoot, ".Sample_Summary_Statistics.csv", sep="");
+ fileSimpleMetricsBySample = paste(evalRoot, ".SimpleMetricsBySample.csv", sep="");
+ fileTi_slash_Tv_Variant_Evaluator = paste(evalRoot, ".Ti_slash_Tv_Variant_Evaluator.csv", sep="");
+ fileTiTvStats = paste(evalRoot, ".TiTvStats.csv", sep="");
+ fileVariant_Quality_Score = paste(evalRoot, ".Variant_Quality_Score.csv", sep="");
+
+ eval = list(
+ AlleleCountStats = NA,
+ CompOverlap = NA,
+ CountVariants = NA,
+ GenotypeConcordance = NA,
+ MetricsByAc = NA,
+ MetricsBySample = NA,
+ Quality_Metrics_by_allele_count = NA,
+ QualityScoreHistogram = NA,
+ SampleStatistics = NA,
+ SampleSummaryStatistics = NA,
+ SimpleMetricsBySample = NA,
+ TiTv = NA,
+ TiTvStats = NA,
+ Variant_Quality_Score = NA,
+
+ CallsetNames = c(),
+ CallsetOnlyNames = c(),
+ CallsetFilteredNames = c()
+ );
+
+ eval$AlleleCountStats = .gsa.attemptToLoadFile(fileAlleleCountStats);
+ eval$CompOverlap = .gsa.attemptToLoadFile(fileCompOverlap);
+ eval$CountVariants = .gsa.attemptToLoadFile(fileCountVariants);
+ eval$GenotypeConcordance = .gsa.attemptToLoadFile(fileGenotypeConcordance);
+ eval$MetricsByAc = .gsa.attemptToLoadFile(fileMetricsByAc);
+ eval$MetricsBySample = .gsa.attemptToLoadFile(fileMetricsBySample);
+ eval$Quality_Metrics_by_allele_count = .gsa.attemptToLoadFile(fileQuality_Metrics_by_allele_count);
+ eval$QualityScoreHistogram = .gsa.attemptToLoadFile(fileQualityScoreHistogram);
+ eval$SampleStatistics = .gsa.attemptToLoadFile(fileSampleStatistics);
+ eval$SampleSummaryStatistics = .gsa.attemptToLoadFile(fileSampleSummaryStatistics);
+ eval$SimpleMetricsBySample = .gsa.attemptToLoadFile(fileSimpleMetricsBySample);
+ eval$TiTv = .gsa.attemptToLoadFile(fileTi_slash_Tv_Variant_Evaluator);
+ eval$TiTvStats = .gsa.attemptToLoadFile(fileTiTvStats);
+ eval$Variant_Quality_Score = .gsa.attemptToLoadFile(fileVariant_Quality_Score);
+
+ uniqueJexlExpressions = unique(eval$TiTv$jexl_expression);
+ eval$CallsetOnlyNames = as.vector(uniqueJexlExpressions[grep("FilteredIn|Intersection|none", uniqueJexlExpressions, invert=TRUE, ignore.case=TRUE)]);
+ eval$CallsetNames = as.vector(gsub("-only", "", eval$CallsetOnlyNames));
+ eval$CallsetFilteredNames = as.vector(c(
+ paste(gsub("^(\\w)", "In\\U\\1", eval$CallsetNames[1], perl=TRUE), "-Filtered", gsub("^(\\w)", "In\\U\\1", eval$CallsetNames[2], perl=TRUE), sep=""),
+ paste(gsub("^(\\w)", "In\\U\\1", eval$CallsetNames[2], perl=TRUE), "-Filtered", gsub("^(\\w)", "In\\U\\1", eval$CallsetNames[1], perl=TRUE), sep=""))
+ );
+
+ if (!(eval$CallsetFilteredNames[1] %in% unique(eval$TiTv$jexl_expression))) {
+ eval$CallsetFilteredNames[1] = paste("In", eval$CallsetNames[1], "-FilteredIn", eval$CallsetNames[2], sep="");
+ }
+
+ if (!(eval$CallsetFilteredNames[2] %in% unique(eval$TiTv$jexl_expression))) {
+ eval$CallsetFilteredNames[2] = paste("In", eval$CallsetNames[2], "-FilteredIn", eval$CallsetNames[1], sep="");
+ #eval$CallsetFilteredNames[2] = paste(gsub("^(\\w)", "In", eval$CallsetNames[2], perl=TRUE), "-Filtered", gsub("^(\\w)", "In", eval$CallsetNames[1], perl=TRUE), sep="");
+ }
+
+ eval;
+}
+
diff --git a/public/R/src/gsalib/R/gsa.read.gatkreport.R b/public/R/src/gsalib/R/gsa.read.gatkreport.R
new file mode 100644
index 000000000..9b3ef1ad1
--- /dev/null
+++ b/public/R/src/gsalib/R/gsa.read.gatkreport.R
@@ -0,0 +1,64 @@
+# Load a table into the specified environment. Make sure that each new table gets a unique name (this allows one to cat a bunch of tables with the same name together and load them into R without each table overwriting the last.
+.gsa.assignGATKTableToEnvironment <- function(tableName, tableHeader, tableRows, tableEnv) {
+ d = data.frame(tableRows, row.names=NULL, stringsAsFactors=FALSE);
+ colnames(d) = tableHeader;
+
+ for (i in 1:ncol(d)) {
+ v = suppressWarnings(as.numeric(d[,i]));
+
+ if (length(na.omit(as.numeric(v))) == length(d[,i])) {
+ d[,i] = v;
+ }
+ }
+
+ usedNames = ls(envir=tableEnv, pattern=tableName);
+
+ if (length(usedNames) > 0) {
+ tableName = paste(tableName, ".", length(usedNames), sep="");
+ }
+
+ assign(tableName, d, envir=tableEnv);
+}
+
+# Load all GATKReport tables from a file
+gsa.read.gatkreport <- function(filename) {
+ con = file(filename, "r", blocking = TRUE);
+ lines = readLines(con);
+ close(con);
+
+ tableEnv = new.env();
+
+ tableName = NA;
+ tableHeader = c();
+ tableRows = c();
+
+ for (line in lines) {
+ if (length(grep("^##:GATKReport.v0.1[[:space:]]+", line, ignore.case=TRUE)) > 0) {
+ headerFields = unlist(strsplit(line, "[[:space:]]+"));
+
+ if (!is.na(tableName)) {
+ .gsa.assignGATKTableToEnvironment(tableName, tableHeader, tableRows, tableEnv);
+ }
+
+ tableName = headerFields[2];
+ tableHeader = c();
+ tableRows = c();
+ } else if (length(grep("^[[:space:]]*$", line)) > 0 | length(grep("^[[:space:]]*#", line)) > 0) {
+ # do nothing
+ } else if (!is.na(tableName)) {
+ row = unlist(strsplit(line, "[[:space:]]+"));
+
+ if (length(tableHeader) == 0) {
+ tableHeader = row;
+ } else {
+ tableRows = rbind(tableRows, row);
+ }
+ }
+ }
+
+ if (!is.na(tableName)) {
+ .gsa.assignGATKTableToEnvironment(tableName, tableHeader, tableRows, tableEnv);
+ }
+
+ gatkreport = as.list(tableEnv);
+}
diff --git a/public/R/src/gsalib/R/gsa.read.squidmetrics.R b/public/R/src/gsalib/R/gsa.read.squidmetrics.R
new file mode 100644
index 000000000..39fa1ad32
--- /dev/null
+++ b/public/R/src/gsalib/R/gsa.read.squidmetrics.R
@@ -0,0 +1,28 @@
+gsa.read.squidmetrics = function(project, bylane = FALSE) {
+ suppressMessages(library(ROracle));
+
+ drv = dbDriver("Oracle");
+ con = dbConnect(drv, "REPORTING/REPORTING@ora01:1521/SEQPROD");
+
+ if (bylane) {
+ statement = paste("SELECT * FROM ILLUMINA_PICARD_METRICS WHERE \"Project\" = '", project, "'", sep="");
+ print(statement);
+
+ rs = dbSendQuery(con, statement = statement);
+ d = fetch(rs, n=-1);
+ dbHasCompleted(rs);
+ dbClearResult(rs);
+ } else {
+ statement = paste("SELECT * FROM ILLUMINA_SAMPLE_STATUS_AGG WHERE \"Project\" = '", project, "'", sep="");
+ print(statement);
+
+ rs = dbSendQuery(con, statement = statement);
+ d = fetch(rs, n=-1);
+ dbHasCompleted(rs);
+ dbClearResult(rs);
+ }
+
+ oraCloseDriver(drv);
+
+ subset(d, Project == project);
+}
diff --git a/public/R/src/gsalib/R/gsa.read.vcf.R b/public/R/src/gsalib/R/gsa.read.vcf.R
new file mode 100644
index 000000000..5beb6455d
--- /dev/null
+++ b/public/R/src/gsalib/R/gsa.read.vcf.R
@@ -0,0 +1,23 @@
+gsa.read.vcf <- function(vcffile, skip=0, nrows=-1, expandGenotypeFields = FALSE) {
+ headers = readLines(vcffile, n=100);
+ headerline = headers[grep("#CHROM", headers)];
+ header = unlist(strsplit(gsub("#", "", headerline), "\t"))
+
+ d = read.table(vcffile, header=FALSE, skip=skip, nrows=nrows, stringsAsFactors=FALSE);
+ colnames(d) = header;
+
+ if (expandGenotypeFields) {
+ columns = ncol(d);
+
+ offset = columns + 1;
+ for (sampleIndex in 10:columns) {
+ gt = unlist(lapply(strsplit(d[,sampleIndex], ":"), function(x) x[1]));
+ d[,offset] = gt;
+ colnames(d)[offset] = sprintf("%s.GT", colnames(d)[sampleIndex]);
+
+ offset = offset + 1;
+ }
+ }
+
+ return(d);
+}
diff --git a/public/R/src/gsalib/R/gsa.warn.R b/public/R/src/gsalib/R/gsa.warn.R
new file mode 100644
index 000000000..7ee08ce65
--- /dev/null
+++ b/public/R/src/gsalib/R/gsa.warn.R
@@ -0,0 +1,3 @@
+gsa.warn <- function(message) {
+ gsa.message(sprintf("Warning: %s", message));
+}
diff --git a/public/R/src/gsalib/Read-and-delete-me b/public/R/src/gsalib/Read-and-delete-me
new file mode 100644
index 000000000..d04323a6e
--- /dev/null
+++ b/public/R/src/gsalib/Read-and-delete-me
@@ -0,0 +1,9 @@
+* Edit the help file skeletons in 'man', possibly combining help files
+ for multiple functions.
+* Put any C/C++/Fortran code in 'src'.
+* If you have compiled code, add a .First.lib() function in 'R' to load
+ the shared library.
+* Run R CMD build to build the package tarball.
+* Run R CMD check to check the package tarball.
+
+Read "Writing R Extensions" for more information.
diff --git a/public/R/src/gsalib/data/tearsheetdrop.jpg b/public/R/src/gsalib/data/tearsheetdrop.jpg
new file mode 100755
index 0000000000000000000000000000000000000000..c9d480fa05f4acf066e3bf1cf469db47b8a1afc3
GIT binary patch
literal 50343
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