Treat ./X genotypes as MIXED so that isHet, isHom, etc. still return the expected and correct values. Added docs to these accessors with contracts explicitly mentioned. Fixed case where NPE could be thrown.

This commit is contained in:
Eric Banks 2011-10-19 15:11:13 -04:00
parent 5a6468c11e
commit d8d73fe4f2
3 changed files with 65 additions and 13 deletions

View File

@ -108,14 +108,19 @@ public class Genotype {
/**
* @return the ploidy of this genotype
*/
public int getPloidy() { return alleles.size(); }
public int getPloidy() {
if ( alleles == null )
throw new ReviewedStingException("Requesting ploidy for an UNAVAILABLE genotype");
return alleles.size();
}
public enum Type {
NO_CALL,
HOM_REF,
HET,
HOM_VAR,
UNAVAILABLE
UNAVAILABLE,
MIXED // no-call and call in the same genotype
}
public Type getType() {
@ -129,36 +134,68 @@ public class Genotype {
if ( alleles == null )
return Type.UNAVAILABLE;
Allele firstAllele = alleles.get(0);
boolean sawNoCall = false, sawMultipleAlleles = false;
Allele observedAllele = null;
if ( firstAllele.isNoCall() ) {
return Type.NO_CALL;
for ( Allele allele : alleles ) {
if ( allele.isNoCall() )
sawNoCall = true;
else if ( observedAllele == null )
observedAllele = allele;
else if ( !allele.equals(observedAllele) )
sawMultipleAlleles = true;
}
for (Allele a : alleles) {
if ( ! firstAllele.equals(a) )
return Type.HET;
if ( sawNoCall ) {
if ( observedAllele == null )
return Type.NO_CALL;
return Type.MIXED;
}
return firstAllele.isReference() ? Type.HOM_REF : Type.HOM_VAR;
if ( observedAllele == null )
throw new ReviewedStingException("BUG: there are no alleles present in this genotype but the alleles list is not null");
return sawMultipleAlleles ? Type.HET : observedAllele.isReference() ? Type.HOM_REF : Type.HOM_VAR;
}
/**
* @return true if all observed alleles are the same (regardless of whether they are ref or alt)
* @return true if all observed alleles are the same (regardless of whether they are ref or alt); if any alleles are no-calls, this method will return false.
*/
public boolean isHom() { return isHomRef() || isHomVar(); }
/**
* @return true if all observed alleles are ref; if any alleles are no-calls, this method will return false.
*/
public boolean isHomRef() { return getType() == Type.HOM_REF; }
/**
* @return true if all observed alleles are alt; if any alleles are no-calls, this method will return false.
*/
public boolean isHomVar() { return getType() == Type.HOM_VAR; }
/**
* @return true if we're het (observed alleles differ)
* @return true if we're het (observed alleles differ); if the ploidy is less than 2 or if any alleles are no-calls, this method will return false.
*/
public boolean isHet() { return getType() == Type.HET; }
/**
* @return true if this genotype is not actually a genotype but a "no call" (e.g. './.' in VCF)
* @return true if this genotype is not actually a genotype but a "no call" (e.g. './.' in VCF); if any alleles are not no-calls (even if some are), this method will return false.
*/
public boolean isNoCall() { return getType() == Type.NO_CALL; }
/**
* @return true if this genotype is comprised of any alleles that are not no-calls (even if some are).
*/
public boolean isCalled() { return getType() != Type.NO_CALL && getType() != Type.UNAVAILABLE; }
/**
* @return true if this genotype is comprised of both calls and no-calls.
*/
public boolean isMixed() { return getType() == Type.MIXED; }
/**
* @return true if the type of this genotype is set.
*/
public boolean isAvailable() { return getType() != Type.UNAVAILABLE; }
//

View File

@ -998,7 +998,7 @@ public class VariantContext implements Feature { // to enable tribble intergrati
else if ( g.isHomVar() )
genotypeCounts[Genotype.Type.HOM_VAR.ordinal()]++;
else
throw new IllegalStateException("Genotype of unknown type: " + g);
genotypeCounts[Genotype.Type.MIXED.ordinal()]++;
}
}
}
@ -1042,6 +1042,15 @@ public class VariantContext implements Feature { // to enable tribble intergrati
return genotypeCounts[Genotype.Type.HOM_VAR.ordinal()];
}
/**
* Genotype-specific functions -- how many mixed calls are there in the genotypes?
*
* @return number of mixed calls
*/
public int getMixedCount() {
return genotypeCounts[Genotype.Type.MIXED.ordinal()];
}
// ---------------------------------------------------------------------------------------------------------
//
// validation: extra-strict validation routines for paranoid users

View File

@ -267,6 +267,12 @@ public class VariantContextUnitTest extends BaseTest {
Assert.assertEquals(vc.getChromosomeCount(), 2); // we know that there are 2 chromosomes, even though one isn't called
Assert.assertEquals(vc.getChromosomeCount(Aref), 0);
Assert.assertEquals(vc.getChromosomeCount(C), 1);
Assert.assertFalse(vc.getGenotype("foo").isHet());
Assert.assertFalse(vc.getGenotype("foo").isHom());
Assert.assertFalse(vc.getGenotype("foo").isNoCall());
Assert.assertFalse(vc.getGenotype("foo").isHom());
Assert.assertTrue(vc.getGenotype("foo").isMixed());
Assert.assertEquals(vc.getGenotype("foo").getType(), Genotype.Type.MIXED);
}
@Test (expectedExceptions = IllegalArgumentException.class)