[med-svn] [picard-tools] 01/04: Imported Upstream version 1.101
Charles Plessy
plessy at alioth.debian.org
Mon Oct 28 10:23:59 UTC 2013
This is an automated email from the git hooks/post-receive script.
plessy pushed a commit to branch master
in repository picard-tools.
commit ff4fd825cb889fd20ac8cbcec0c288184306c620
Author: Charles Plessy <plessy at debian.org>
Date: Mon Oct 28 19:11:31 2013 +0900
Imported Upstream version 1.101
---
build.xml | 2 +-
src/java/net/sf/picard/pedigree/PedFile.java | 99 +++++++++++
src/java/net/sf/picard/pedigree/PedTrio.java | 45 +++++
src/java/net/sf/picard/pedigree/Sex.java | 26 +++
src/java/net/sf/picard/util/MathUtil.java | 17 ++
src/java/net/sf/samtools/util/Iso8601Date.java | 2 +-
.../net/sf/samtools/util/RelativeIso8601Date.java | 187 ++++++++++++++++++++
.../org/broadinstitute/variant/vcf/VCFCodec.java | 4 +-
.../broadinstitute/variant/vcf/VCFFileReader.java | 40 +++--
.../sf/samtools/util/RelativeIso8601DateTest.java | 39 ++++
10 files changed, 442 insertions(+), 19 deletions(-)
diff --git a/build.xml b/build.xml
index 5b6c3bd..e5c07bc 100755
--- a/build.xml
+++ b/build.xml
@@ -43,7 +43,7 @@
<!-- Get SVN revision, if available, otherwise leave it blank. -->
<exec executable="svnversion" outputproperty="repository.revision" failifexecutionfails="false"/>
<property name="repository.revision" value=""/>
- <property name="sam-version" value="1.100"/>
+ <property name="sam-version" value="1.101"/>
<property name="picard-version" value="${sam-version}"/>
<property name="tribble-version" value="${sam-version}"/>
<property name="variant-version" value="${sam-version}"/>
diff --git a/src/java/net/sf/picard/pedigree/PedFile.java b/src/java/net/sf/picard/pedigree/PedFile.java
new file mode 100644
index 0000000..1a429d6
--- /dev/null
+++ b/src/java/net/sf/picard/pedigree/PedFile.java
@@ -0,0 +1,99 @@
+package net.sf.picard.pedigree;
+
+import net.sf.picard.io.IoUtil;
+import net.sf.picard.util.Log;
+import net.sf.samtools.util.RuntimeIOException;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.regex.Pattern;
+
+/**
+ * Represents a .ped file of family information as documented here:
+ * http://pngu.mgh.harvard.edu/~purcell/plink/data.shtml
+ *
+ * Stores the information in memory as a map of individualId -> Pedigree information for that individual
+ */
+public class PedFile extends TreeMap<String,PedTrio> {
+ private static final Log log = Log.getInstance(PedFile.class);
+ static final Pattern WHITESPACE = Pattern.compile("\\s+");
+
+ /** Adds a trio to the PedFile keyed by the individual id. */
+ public void add(final PedTrio trio) {
+ put(trio.getIndividualId(), trio);
+ }
+
+ /**
+ * Writes a set of pedigrees out to disk.
+ */
+ public void write(final File file) {
+ IoUtil.assertFileIsWritable(file);
+ final BufferedWriter out = IoUtil.openFileForBufferedWriting(file);
+
+ try {
+ for (final PedTrio trio : values()) {
+ out.write(trio.getFamilyId());
+ out.write("\t");
+ out.write(trio.getIndividualId());
+ out.write("\t");
+ out.write(trio.getPaternalId());
+ out.write("\t");
+ out.write(trio.getMaternalId());
+ out.write("\t");
+ out.write(String.valueOf(trio.getSex().toCode()));
+ out.write("\t");
+ out.write(trio.getPhenotype().toString());
+ out.newLine();
+ }
+
+ out.close();
+ }
+ catch (IOException ioe) {
+ throw new RuntimeIOException("IOException while writing to file " + file.getAbsolutePath(), ioe);
+ }
+ }
+
+ /**
+ * Attempts to read a pedigree file into memory.
+ */
+ public static PedFile fromFile(final File file) {
+ final PedFile pedfile = new PedFile();
+
+ IoUtil.assertFileIsReadable(file);
+ for (final String line : IoUtil.readLines(file)) {
+ final String[] fields = WHITESPACE.split(line);
+ if (fields.length != 6) {
+ log.error("Ped file line contained invalid number of fields, skipping: " + line);
+ continue;
+ }
+
+ final PedTrio trio = new PedTrio(fields[0],
+ fields[1],
+ fields[2],
+ fields[3],
+ Sex.fromCode(Integer.parseInt(fields[4])),
+ fields[5].contains(".") ? Double.parseDouble(fields[5]) : Integer.parseInt(fields[5])
+ );
+ pedfile.add(trio);
+ }
+
+ return pedfile;
+ }
+
+ /**
+ * Scans through the pedigrees and removes all entries that do not have both paternal and maternal ids set.
+ */
+ public PedFile removeIncompleteTrios() {
+ final Iterator<Map.Entry<String,PedTrio>> iterator = entrySet().iterator();
+
+ while (iterator.hasNext()) {
+ if (!iterator.next().getValue().hasBothParents()) iterator.remove();
+ }
+
+ return this;
+ }
+}
diff --git a/src/java/net/sf/picard/pedigree/PedTrio.java b/src/java/net/sf/picard/pedigree/PedTrio.java
new file mode 100644
index 0000000..8288625
--- /dev/null
+++ b/src/java/net/sf/picard/pedigree/PedTrio.java
@@ -0,0 +1,45 @@
+package net.sf.picard.pedigree;
+
+/**
+ * Represents a single trio within a ped file.
+ *
+ * @author Tim Fennell
+ */
+public class PedTrio {
+ public static final Number NO_PHENO = new Integer(-9);
+ public static final Sex UNKNOWN_SEX = Sex.Unknown;
+
+ private final String familyId;
+ private final String individualId;
+ private final String paternalId;
+ private final String maternalId;
+ private final Sex sex;
+ private final Number phenotype;
+
+ /** Constructs a TRIO that cannot be modified after the fact. */
+ public PedTrio(final String familyId, final String individualId, final String paternalId, final String maternalId, final Sex sex, final Number phenotype) {
+ if (PedFile.WHITESPACE.split(familyId).length != 1) throw new IllegalArgumentException("FamilyID cannot contain whitespace: [" + familyId + "]");
+ if (PedFile.WHITESPACE.split(individualId).length != 1) throw new IllegalArgumentException("IndividualID cannot contain whitespace: [" + individualId + "]");
+ if (PedFile.WHITESPACE.split(paternalId).length != 1) throw new IllegalArgumentException("PaternalID cannot contain whitespace: [" + paternalId + "]");
+ if (PedFile.WHITESPACE.split(maternalId).length != 1) throw new IllegalArgumentException("MaternalID cannot contain whitespace: [" + maternalId + "]");
+
+ this.familyId = familyId;
+ this.individualId = individualId;
+ this.paternalId = paternalId;
+ this.maternalId = maternalId;
+ this.sex = sex;
+ this.phenotype = phenotype;
+ }
+
+ /** True if this record has paternal and maternal ids, otherwise false. */
+ public boolean hasBothParents() {
+ return this.paternalId != null && this.maternalId != null;
+ }
+
+ public String getFamilyId() { return familyId; }
+ public String getIndividualId() { return individualId; }
+ public String getPaternalId() { return paternalId; }
+ public String getMaternalId() { return maternalId; }
+ public Sex getSex() { return sex; }
+ public Number getPhenotype() { return phenotype; }
+}
diff --git a/src/java/net/sf/picard/pedigree/Sex.java b/src/java/net/sf/picard/pedigree/Sex.java
new file mode 100644
index 0000000..812bc55
--- /dev/null
+++ b/src/java/net/sf/picard/pedigree/Sex.java
@@ -0,0 +1,26 @@
+package net.sf.picard.pedigree;
+
+/**
+ * Represents the sex of an individual.
+ */
+public enum Sex {
+ Male(1), Female(2), Unknown(-9);
+
+ /** The integer code used when reading/writing ped files. */
+ private final int code;
+
+ /** Private constructor that takes the pedigree code for sex. */
+ private Sex(final int code) {
+ this.code = code;
+ }
+
+ /** Returns the code used to encode this sex in a ped/fam file. */
+ public int toCode() { return this.code;}
+
+ /** Decodes the Sex from a numeric code. Note that any value other than 1 or 2 will return Unknown. */
+ public static Sex fromCode(final int code) {
+ if (code == Male.code) return Male;
+ else if (code == Female.code) return Female;
+ else return Unknown;
+ }
+}
diff --git a/src/java/net/sf/picard/util/MathUtil.java b/src/java/net/sf/picard/util/MathUtil.java
index 77edaaa..192e350 100644
--- a/src/java/net/sf/picard/util/MathUtil.java
+++ b/src/java/net/sf/picard/util/MathUtil.java
@@ -147,4 +147,21 @@ public class MathUtil {
return tmp;
}
+
+ /** Calculates the product of two arrays of the same length. */
+ public static double[] multiply(final double[] lhs, final double[] rhs) {
+ if (lhs.length != rhs.length) throw new IllegalArgumentException("Arrays must be of same length.");
+
+ final int len = lhs.length;
+ final double[] result = new double[len];
+ for (int i=0; i<len; ++i) result[i] = lhs[i] * rhs[i];
+ return result;
+ }
+
+ /** Returns the sum of the elements in the array. */
+ public static double sum(final double[] arr) {
+ double result = 0;
+ for (final double next : arr) result += next;
+ return result;
+ }
}
diff --git a/src/java/net/sf/samtools/util/Iso8601Date.java b/src/java/net/sf/samtools/util/Iso8601Date.java
index 96b234b..3d969eb 100644
--- a/src/java/net/sf/samtools/util/Iso8601Date.java
+++ b/src/java/net/sf/samtools/util/Iso8601Date.java
@@ -59,7 +59,7 @@ public class Iso8601Date extends Date {
long time = getTime();
long mod = time % 1000;
if (mod != 0) {
- setTime(time - mod);
+ super.setTime(time - mod);
}
}
}
diff --git a/src/java/net/sf/samtools/util/RelativeIso8601Date.java b/src/java/net/sf/samtools/util/RelativeIso8601Date.java
new file mode 100644
index 0000000..0a9a4b4
--- /dev/null
+++ b/src/java/net/sf/samtools/util/RelativeIso8601Date.java
@@ -0,0 +1,187 @@
+package net.sf.samtools.util;
+
+import java.util.Date;
+
+/**
+ * Like {@link Iso8601Date}, but also comes in a "lazy now" flavor.
+ *
+ * When "lazy now" mode is enabled, this instance's date value is undefined until the first time it is queried, at which time it is set to
+ * {@link System#currentTimeMillis()}. This value is returned on subsequent queries, so it is consistent.
+ *
+ * The "lazy state" is conveyed via {@link #toString()}. A "lazy now" instance will answer {@link #toString()} with
+ * {@link #LAZY_NOW_LABEL} if the time has not yet been queried/set, or a {@link Iso8601Date}-formatted date of the query time if it
+ * has been queried. This characteristic is useful for serialization and persistence purposes.
+ *
+ * Consumers can create "lazy now" instances via the {@link #generateLazyNowInstance()} factory method or by passing {@link #LAZY_NOW_LABEL} to
+ * {@link #RelativeIso8601Date(String)}.
+ *
+ * @author mccowan
+ */
+public class RelativeIso8601Date extends Iso8601Date {
+
+ public static final String LAZY_NOW_LABEL = "NOW";
+
+ /** Flag that indicates this instance is lazy and has not yet been queried (and so its value should be updated at the next query). */
+ private boolean doSetTimeNextQuery;
+
+ /** Returns a "lazy now" instance. */
+ public static RelativeIso8601Date generateLazyNowInstance() {
+ return new RelativeIso8601Date(LAZY_NOW_LABEL);
+ }
+
+ public RelativeIso8601Date(final Date date) {
+ super(date);
+ doSetTimeNextQuery = false;
+ }
+
+ public RelativeIso8601Date(final String dateStr) {
+ /**
+ * We must pass a date parsable {@link Iso8601Date#Iso8601Date(String)}; we will never actually read the passed value, so it doesn't
+ * matter what it is.
+ */
+ super(LAZY_NOW_LABEL.equals(dateStr) ? new Iso8601Date(new Date()).toString() : dateStr);
+ doSetTimeNextQuery = LAZY_NOW_LABEL.equals(dateStr);
+ }
+
+ /** Updates the time stored by this instance if it's a "lazy now" instance and has never been stored. */
+ private synchronized void conditionallyUpdateTime() {
+ if (!doSetTimeNextQuery) {
+ super.setTime(System.currentTimeMillis());
+ doSetTimeNextQuery = false;
+ }
+ }
+
+ /**
+ * Returns a {@link String} representation of this date.
+ * @return An {@link Iso8601Date}-formatted string, or the value of {@link #LAZY_NOW_LABEL} if this is a "lazy now" instance.
+ */
+ @Override
+ public String toString() {
+ return doSetTimeNextQuery ? LAZY_NOW_LABEL : super.toString();
+ }
+
+ @Override
+ public long getTime() {
+ conditionallyUpdateTime();
+ return super.getTime();
+ }
+
+ @Override
+ public boolean after(final Date when) {
+ conditionallyUpdateTime();
+ return super.after(when);
+ }
+
+ @Override
+ public boolean before(final Date when) {
+ conditionallyUpdateTime();
+ return super.before(when);
+ }
+
+ @Override
+ public Object clone() {
+ conditionallyUpdateTime();
+ return super.clone();
+ }
+
+ @Override
+ public int compareTo(final Date anotherDate) {
+ conditionallyUpdateTime();
+ return super.compareTo(anotherDate);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ conditionallyUpdateTime();
+ return super.equals(obj);
+ }
+
+ @Override
+ public int getDate() {
+ conditionallyUpdateTime();
+ return super.getDate();
+ }
+
+ @Override
+ public int getDay() {
+ conditionallyUpdateTime();
+ return super.getDay();
+ }
+
+ @Override
+ public int getHours() {
+ conditionallyUpdateTime();
+ return super.getHours();
+ }
+
+ @Override
+ public int getMinutes() {
+ conditionallyUpdateTime();
+ return super.getMinutes();
+ }
+
+ @Override
+ public int getMonth() {
+ conditionallyUpdateTime();
+ return super.getMonth();
+ }
+
+ @Override
+ public int getSeconds() {
+ conditionallyUpdateTime();
+ return super.getSeconds();
+ }
+
+ @Override
+ public int getTimezoneOffset() {
+ conditionallyUpdateTime();
+ return super.getTimezoneOffset();
+ }
+
+ @Override
+ public int getYear() {
+ conditionallyUpdateTime();
+ return super.getYear();
+ }
+
+ @Override
+ public int hashCode() {
+ conditionallyUpdateTime();
+ return super.hashCode();
+ }
+
+ @Override
+ public void setDate(final int date) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setHours(final int hours) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setMinutes(final int minutes) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setMonth(final int month) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setSeconds(final int seconds) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setTime(final long time) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setYear(final int year) {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/src/java/org/broadinstitute/variant/vcf/VCFCodec.java b/src/java/org/broadinstitute/variant/vcf/VCFCodec.java
index 50a4f08..5107ff7 100644
--- a/src/java/org/broadinstitute/variant/vcf/VCFCodec.java
+++ b/src/java/org/broadinstitute/variant/vcf/VCFCodec.java
@@ -121,7 +121,7 @@ public class VCFCodec extends AbstractVCFCodec {
* @param filterString the string to parse
* @return a set of the filters applied or null if filters were not applied to the record (e.g. as per the missing value in a VCF)
*/
- protected List<String> parseFilters(String filterString) {
+ protected List<String> parseFilters(final String filterString) {
// null for unfiltered
if ( filterString.equals(VCFConstants.UNFILTERED) )
return null;
@@ -138,7 +138,7 @@ public class VCFCodec extends AbstractVCFCodec {
return filterHash.get(filterString);
// empty set for passes filters
- List<String> fFields = new LinkedList<String>();
+ final List<String> fFields = new LinkedList<String>();
// otherwise we have to parse and cache the value
if ( !filterString.contains(VCFConstants.FILTER_CODE_SEPARATOR) )
fFields.add(filterString);
diff --git a/src/java/org/broadinstitute/variant/vcf/VCFFileReader.java b/src/java/org/broadinstitute/variant/vcf/VCFFileReader.java
index 3f3eb3a..6ed9251 100644
--- a/src/java/org/broadinstitute/variant/vcf/VCFFileReader.java
+++ b/src/java/org/broadinstitute/variant/vcf/VCFFileReader.java
@@ -13,7 +13,10 @@ import java.io.Closeable;
import java.io.File;
import java.io.IOException;
-public class VCFFileReader implements Closeable {
+/**
+ * Simplified interface for reading from VCF/BCF files.
+ */
+public class VCFFileReader implements Closeable, Iterable<VariantContext> {
private final FeatureReader<VariantContext> reader;
@@ -33,37 +36,44 @@ public class VCFFileReader implements Closeable {
return dict;
}
+ /** Constructs a VCFFileReader that requires the index to be present. */
public VCFFileReader(final File file) {
this(file, true);
}
- public VCFFileReader(final File file, boolean requireIndex) {
- this.reader =
- AbstractFeatureReader.getFeatureReader(
+ /** Allows construction of a VCFFileReader that will or will not assert the presence of an index as desired. */
+ public VCFFileReader(final File file, final boolean requireIndex) {
+ this.reader = AbstractFeatureReader.getFeatureReader(
file.getAbsolutePath(),
- isBCF(file)
- ? new BCF2Codec()
- : new VCFCodec(),
+ isBCF(file) ? new BCF2Codec() : new VCFCodec(),
requireIndex);
}
+ /** Returns the VCFHeader associated with this VCF/BCF file. */
public VCFHeader getFileHeader() {
return (VCFHeader) reader.getHeader();
}
+ /** Returns an iterator over all records in this VCF/BCF file. */
public CloseableIterator<VariantContext> iterator() {
- try {
- return reader.iterator();
- } catch (final IOException ioe) {
- throw new TribbleException("Could not create an iterator from a feature reader: " + ioe.getMessage(), ioe);
+ try { return reader.iterator(); }
+ catch (final IOException ioe) {
+ throw new TribbleException("Could not create an iterator from a feature reader.", ioe);
}
}
+ /** Queries for records within the region specified. */
+ public CloseableIterator<VariantContext> query(final String chrom, final int start, final int end) {
+ try { return reader.query(chrom, start, end); }
+ catch (final IOException ioe) {
+ throw new TribbleException("Could not create an iterator from a feature reader.", ioe);
+ }
+ }
+
public void close() {
- try {
- this.reader.close();
- } catch (final IOException ioe) {
- throw new TribbleException("Could not close a variant context feature reader: " + ioe.getMessage(), ioe);
+ try { this.reader.close(); }
+ catch (final IOException ioe) {
+ throw new TribbleException("Could not close a variant context feature reader.", ioe);
}
}
}
diff --git a/src/tests/java/net/sf/samtools/util/RelativeIso8601DateTest.java b/src/tests/java/net/sf/samtools/util/RelativeIso8601DateTest.java
new file mode 100644
index 0000000..f4a91f0
--- /dev/null
+++ b/src/tests/java/net/sf/samtools/util/RelativeIso8601DateTest.java
@@ -0,0 +1,39 @@
+package net.sf.samtools.util;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+/** @author mccowan */
+
+public class RelativeIso8601DateTest {
+ @Test
+ public void testLazyInstance() {
+ final RelativeIso8601Date lazy = RelativeIso8601Date.generateLazyNowInstance();
+ Assert.assertEquals(lazy.toString(), RelativeIso8601Date.LAZY_NOW_LABEL);
+ Assert.assertEquals(lazy.toString(), RelativeIso8601Date.LAZY_NOW_LABEL);
+ Assert.assertEquals(lazy.toString(), RelativeIso8601Date.LAZY_NOW_LABEL);
+ Assert.assertEquals((double) lazy.getTime(), (double) System.currentTimeMillis(), 2000d); // Up to 2 seconds off; iso truncates milliseconds.
+ // Assert no exception thrown; this should be valid, because toString should now return an iso-looking date.
+ new RelativeIso8601Date(lazy.toString());
+ }
+
+ @Test
+ public void testNonLazyInstance() {
+ // Test both constructor methods
+ final List<RelativeIso8601Date> testDates = Arrays.<RelativeIso8601Date>asList(
+ new RelativeIso8601Date(new Date()),
+ new RelativeIso8601Date(new Iso8601Date(new Date()).toString())
+ );
+
+ for (final RelativeIso8601Date nonLazy : testDates) {
+ Assert.assertFalse(nonLazy.toString().equals(RelativeIso8601Date.LAZY_NOW_LABEL));
+ Assert.assertEquals((double) nonLazy.getTime(), (double) System.currentTimeMillis(), 1d);
+ // Assert no exception thrown; this should be valid, because toString return an iso-looking date.
+ new RelativeIso8601Date(nonLazy.toString());
+ }
+ }
+}
--
Alioth's /git/debian-med/git-commit-notice on /srv/git.debian.org/git/debian-med/picard-tools.git
More information about the debian-med-commit
mailing list