Esempio n. 1
0
    def setUp(self):
        """ define a family and variant, and start the Autosomal class
        """

        # generate a test family
        child_gender = "F"
        mom_aff = "1"
        dad_aff = "1"

        self.trio = self.create_family(child_gender, mom_aff, dad_aff)

        # generate a test variant
        child_var = self.create_snv(child_gender, "0/1")
        mom_var = self.create_snv("F", "0/0")
        dad_var = self.create_snv("M", "0/0")

        var = TrioGenotypes(child_var)
        var.add_mother_variant(mom_var)
        var.add_father_variant(dad_var)
        self.variants = [var]

        # make sure we've got known genes data
        self.known_genes = {
            "TEST": {
                "inh": ["Monoallelic"],
                "confirmed_status": ["Confirmed DD Gene"]
            }
        }

        self.inh = Autosomal(self.variants, self.trio, self.known_genes,
                             "TEST")
        self.inh.is_lof = var.child.is_lof()
    def setUp(self):
        """ define a family and variant, and start the Inheritance class
        """

        # generate a test family
        child_gender = "F"
        mom_aff = "1"
        dad_aff = "1"

        self.trio = self.create_family(child_gender, mom_aff, dad_aff)

        # generate list of variants
        self.variants = [self.create_variant(child_gender)]
        self.variants.append(self.create_variant(child_gender))

        # make sure we've got known genes data
        self.known_genes = {
            "TEST": {
                "inh": ["Monoallelic"],
                "confirmed_status": ["Confirmed DD Gene"]
            }
        }

        self.inh = Autosomal(self.variants, self.trio, self.known_genes,
                             "TEST")
    def setUp(self):
        """ define a family and variant, and start the Autosomal class
        """

        # generate a test family
        sex = "F"
        mom_aff = "1"
        dad_aff = "1"

        self.trio = self.create_family(sex, mom_aff, dad_aff)

        # generate a test variant
        child = create_snv(sex, "0/1")
        mom = create_snv("F", "0/0")
        dad = create_snv("M", "0/0")

        var = TrioGenotypes(child.get_chrom(), child.get_position(), child,
                            mom, dad)
        self.variants = [var]

        # make sure we've got known genes data
        self.known_gene = {
            "inh": ["Monoallelic"],
            "confirmed_status": ["confirmed dd gene"]
        }

        self.inh = Autosomal(self.variants, self.trio, self.known_gene, "1001")
        self.inh.is_lof = var.child.is_lof()
Esempio n. 4
0
 def find_variants(self, variants, gene, family):
     """ finds variants that fit inheritance models
     
     Args:
         variants: list of TrioGenotype objects
         gene: gene ID as string
     
     Returns:
         list of variants that pass inheritance checks
     """
     
     # get the inheritance for the gene (monoalleleic, biallelic, hemizygous
     # etc), but allow for times when we haven't specified a list of genes
     # to use
     known_gene = None
     gene_inh = None
     if self.known_genes is not None and gene in self.known_genes:
         known_gene = self.known_genes[gene]
         gene_inh = known_gene['inh']
     
     chrom_inheritance = variants[0].get_inheritance_type()
     
     # If we are looking for variants in a set of known genes, and the gene
     # isn't part of that set, then we don't ant to examine the variant for
     # that gene, UNLESS the variant is a CNV, since CNVs can be included
     # purely from size thresholds, regardless of which gene they overlap.
     if self.known_genes is not None and gene not in self.known_genes:
         variants = [ x for x in variants if x.is_cnv() ]
     
     # ignore intergenic variants
     if gene is None:
         for var in variants:
             if var.get_chrom() == self.debug_chrom and var.get_position() == self.debug_pos:
                 print(var, "lacks HGNC/gene symbol")
         return []
     
     # Now that we are examining a single gene, check that the consequences
     # for the gene are in the required functional categories.
     variants = [ var for var in variants if var.child.is_lof(gene) or var.child.is_missense(var.child.is_cnv(), gene) ]
     if variants == []:
         return []
     
     for x in variants[0].child.info.symbols:
         try:
             symbol = x.get(gene, ['HGNC', 'SYMBOL', 'ENSG'])
             break
         except KeyError:
             continue
     logging.info("{}\t{}\tvariants: {}\trequired_mode: {}".format(
         family.child.get_id(), symbol, [str(x) for x in variants], gene_inh))
     
     if chrom_inheritance == "autosomal":
         finder = Autosomal(variants, family, known_gene, gene, self.cnv_regions)
     elif chrom_inheritance in ["XChrMale", "XChrFemale", "YChrMale"]:
         finder = Allosomal(variants, family, known_gene, gene, self.cnv_regions)
     
     return finder.get_candidate_variants()
    def find_variants(self, variants, gene):
        """ finds variants that fit inheritance models
        
        Args:
            variants: list of TrioGenotype objects
            gene: gene ID as string
        
        Returns:
            list of variants that pass inheritance checks
        """

        # get the inheritance for the gene (monoalleleic, biallelic, hemizygous
        # etc), but allow for times when we haven't specified a list of genes
        # to use
        gene_inh = None
        if self.known_genes is not None and gene in self.known_genes:
            gene_inh = self.known_genes[gene]["inh"]

        # If we are looking for variants in a set of known genes, and the gene
        # isn't part of that set, then we don't ant to examine the variant for
        # that gene, UNLESS the variant is a CNV, since CNVs can be included
        # purely from size thresholds, regardless of which gene they overlap.
        if self.known_genes is not None and gene not in self.known_genes:
            variants = [x for x in variants if x.is_cnv()]

        # ignore intergenic variants
        if gene is None:
            for var in variants:
                if var.get_chrom() == self.debug_chrom and var.get_position(
                ) == self.debug_pos:
                    print(var, "lacks HGNC/gene symbol")
            return []

        # Now that we are examining a single gene, check that the consequences
        # for the gene are in the required functional categories.
        variants = [
            var for var in variants
            if var.child.is_lof(gene) or var.child.is_missense(gene)
        ]
        if variants == []:
            return []

        logging.debug("{} {} {} {}".format(self.family.child.get_id(), gene,
                                           variants, gene_inh))
        chrom_inheritance = variants[0].get_inheritance_type()

        if chrom_inheritance == "autosomal":
            finder = Autosomal(variants, self.family, self.known_genes, gene,
                               self.cnv_regions)
        elif chrom_inheritance in ["XChrMale", "XChrFemale", "YChrMale"]:
            finder = Allosomal(variants, self.family, self.known_genes, gene,
                               self.cnv_regions)

        variants = finder.get_candidate_variants()
        variants = [(x[0], list(x[1]), list(x[2]), [gene]) for x in variants]

        return variants
    def test_check_compound_hets(self):
        """ test that check_compound_hets() works correctly for autosomal vars
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant("F",
                                   chrom="1",
                                   position="15000000",
                                   cq="stop_gained")
        var2 = self.create_variant("F",
                                   chrom="1",
                                   position="16000000",
                                   cq="stop_gained")
        var3 = self.create_variant("F",
                                   chrom="1",
                                   position="17000000",
                                   cq="stop_gained")

        # set the inheritance type, the compound het type ("compound_het"
        # for autosomal variants, and start autosomal inheritance)
        # known_genes = "Biallelic"
        known_genes = {
            "TEST": {
                "inh": ["Biallelic"],
                "confirmed_status": ["Confirmed DD Gene"]
            }
        }
        self.inh = Autosomal([var1, var2, var3], self.trio, known_genes,
                             "TEST")

        variants = [(), ()]

        # check the expected "110, 101" combo passes
        variants[0] = (self.set_compound_het_var(var1, "110"), )
        variants[1] = (self.set_compound_het_var(var2, "101"), )
        self.assertEqual(sorted(self.inh.check_compound_hets(variants)),
                         sorted(variants))

        # check that > 2 valid compound hets passes all variants
        variants = [(), (), ()]
        variants[0] = (self.set_compound_het_var(var1, "110"), )
        variants[1] = (self.set_compound_het_var(var2, "101"), )
        variants[2] = (self.set_compound_het_var(var3, "110"), )
        self.assertEqual(sorted(self.inh.check_compound_hets(variants)),
                         sorted(variants))

        # check that a single var fails to give compound hets
        single_var = variants[:1]
        self.assertEqual(self.inh.check_compound_hets(single_var), [])

        # check that zero length list gives no compound hets
        no_vars = []
        self.assertEqual(self.inh.check_compound_hets(no_vars), [])
    def find_variants(self, variants, gene):
        """ finds variants that fit inheritance models
        
        Args:
            variants: list of TrioGenotype objects
            gene: gene ID as string
        
        Returns:
            list of variants that pass inheritance checks
        """

        # get the inheritance for the gene (monoalleleic, biallelic, hemizygous
        # etc), but allow for times when we haven't specified a list of genes
        # to use
        gene_inh = None
        if self.known_genes is not None and gene in self.known_genes:
            gene_inh = self.known_genes[gene]["inh"]

        # If we are looking for variants in a set of known genes, and the gene
        # isn't part of that set, then we don't ant to examine the variant for
        # that gene, UNLESS the variant is a CNV, since CNVs can be included
        # purely from size thresholds, regardless of which gene they overlap.
        if self.known_genes is not None and gene not in self.known_genes:
            variants = [x for x in variants if x.is_cnv()]

        # ignore intergenic variants
        if gene is None:
            for var in variants:
                if var.get_chrom() == self.debug_chrom and var.get_position() == self.debug_pos:
                    print(var, "lacks HGNC/gene symbol")
            return []

        # Now that we are examining a single gene, check that the consequences
        # for the gene are in the required functional categories.
        variants = [var for var in variants if var.child.is_lof(gene) or var.child.is_missense(gene)]
        if variants == []:
            return []

        logging.debug("{} {} {} {}".format(self.family.child.get_id(), gene, variants, gene_inh))
        chrom_inheritance = variants[0].get_inheritance_type()

        if chrom_inheritance == "autosomal":
            finder = Autosomal(variants, self.family, self.known_genes, gene, self.cnv_regions)
        elif chrom_inheritance in ["XChrMale", "XChrFemale", "YChrMale"]:
            finder = Allosomal(variants, self.family, self.known_genes, gene, self.cnv_regions)

        variants = finder.get_candidate_variants()
        variants = [(x[0], list(x[1]), list(x[2]), [gene]) for x in variants]

        return variants
 def setUp(self):
     """ define a family and variant, and start the Autosomal class
     """
     
     # generate a test family
     child_gender = "F"
     mom_aff = "1"
     dad_aff = "1"
     
     self.trio = self.create_family(child_gender, mom_aff, dad_aff)
     
     # generate a test variant
     child_var = self.create_snv(child_gender, "0/1")
     mom_var = self.create_snv("F", "0/0")
     dad_var = self.create_snv("M", "0/0")
     
     var = TrioGenotypes(child_var)
     var.add_mother_variant(mom_var)
     var.add_father_variant(dad_var)
     self.variants = [var]
     
     # make sure we've got known genes data
     self.known_genes = {"TEST": {"inh": ["Monoallelic"], "confirmed_status": ["Confirmed DD Gene"]}}
     
     self.inh = Autosomal(self.variants, self.trio, self.known_genes, "TEST")
     self.inh.is_lof = var.child.is_lof()
 def test_is_compound_pair_proband_only(self):
     """ check that is_compound_pair() includes proband-only pairs
     """
     
     fam = Family("test")
     fam.add_child("child", 'dad_id', 'mom_id', 'F', '2',  "child_vcf")
     fam.set_child()
     
     # set some variants, so we can alter them later
     var1 = self.create_variant(chrom="1", position="150", sex="F", cq="stop_gained")
     var2 = self.create_variant(chrom="1", position="160", sex="F", cq="stop_gained")
     
     inh = Autosomal([var1, var2], fam, self.known_gene, "TEST")
     
     # check that a proband-only passes, regardless of the parental genotypes
     self.assertTrue(inh.is_compound_pair(var1, var2))
 def test_get_candidate_variants_monoallelic(self):
     """ test that get_candidate_variants() works for a monoallelic variant
     """
     
     inh = {"inh": ["Monoallelic"], "confirmed_status": ["confirmed dd gene"]}
     var = self.create_variant(position='150', cq='stop_gained',
         geno=['0/1', '0/0', '0/0'])
     self.inh = Autosomal([var], self.trio, inh, "TEST")
     
     self.assertEqual(self.inh.get_candidate_variants(),
         [(var, ['single_variant'], ['Monoallelic'], ['TEST'])])
     
     # check a variant that shouldn't pass the monoallelic route
     var = self.create_variant(position='150', cq='stop_gained',
         geno=['0/1', '0/1', '0/0'])
     self.inh = Autosomal([var], self.trio, inh, "TEST")
     self.assertEqual(self.inh.get_candidate_variants(), [])
 def test_get_candidate_variants_compound_het(self):
     """ test that get_candidate_variants() works for biallelic variants
     """
     
     inh = {"inh": ["Biallelic"], "confirmed_status": ["confirmed dd gene"]}
     var1 = self.create_variant(position='150', cq='stop_gained',
         geno=['0/1', '0/1', '0/0'])
     var2 = self.create_variant(position='151', cq='stop_gained',
         geno=['0/1', '0/0', '1/0'])
     self.inh = Autosomal([var1, var2], self.trio, inh, "TEST")
     
     self.assertEqual(sorted(self.inh.get_candidate_variants()),
         sorted([(var1, ['compound_het'], ['Biallelic'], ['TEST']),
         (var2, ['compound_het'], ['Biallelic'], ['TEST'])]))
     
     # check that a single variant isn't included in the compound hets
     self.inh = Autosomal([var1], self.trio, inh, "TEST")
     self.assertEqual(self.inh.get_candidate_variants(), [])
 def test_get_candidate_variants_imprinted(self):
     """ test that get_candidate_variants() works for imprinted variants
     """
     
     # check a variant where the imprinting route should work
     inh = {"inh": ["Imprinted"], "confirmed_status": ["confirmed dd gene"]}
     var = self.create_variant(position='150', cq='stop_gained',
         geno=['0/1', '0/1', '0/0'])
     self.inh = Autosomal([var], self.trio, inh, "TEST")
     
     self.assertEqual(self.inh.get_candidate_variants(),
         [(var, ['single_variant'], ['Imprinted'], ['TEST'])])
     
     # de novos should now pass the imprinted route
     var = self.create_variant(position='150', cq='stop_gained',
         geno=['0/1', '0/0', '0/0'])
     self.inh = Autosomal([var], self.trio, inh, "TEST")
     #self.assertEqual(self.inh.get_candidate_variants(), [])
     self.assertEqual(self.inh.get_candidate_variants(),
         [(var, ['single_variant'], ['Imprinted'], ['TEST'])])
     
     # check a variant that shouldn't pass the imprinted route due to there
     # not being a known gene.
     # NOTE: this behavior differs differs slightly from other inheritance
     # modes when there isn't any known gene. Since there are so few known
     # imprinting genes, it makes sense to only allow for these when we know
     # the mode is correct
     var = self.create_variant(position='150', cq='stop_gained',
         geno=['0/1', '0/1', '0/0'])
     self.inh = Autosomal([var], self.trio, None, "TEST")
     self.assertEqual(self.inh.get_candidate_variants(), [])
     
     # also check imprinting requires loss-of-function consequences
     var = self.create_variant(position='150', cq='missense_variant',
         geno=['0/1', '0/1', '0/0'])
     self.inh = Autosomal([var], self.trio, inh, "TEST")
     self.assertEqual(self.inh.get_candidate_variants(), [])
     
     # check loss-of-function requirement for a paternally inherited variant
     var = self.create_variant(position='150', cq='missense_variant',
         geno=['0/1', '0/0', '0/1'])
     self.inh = Autosomal([var], self.trio, inh, "TEST")
     self.assertEqual(self.inh.get_candidate_variants(), [])
     
     # check imprinting for a biallelic variant
     var = self.create_variant(position='150', cq='stop_gained',
         geno=['1/1', '0/1', '0/1'])
     self.inh = Autosomal([var], self.trio, inh, "TEST")
     self.assertEqual(self.inh.get_candidate_variants(),
         [(var, ['single_variant'], ['Imprinted'], ['TEST'])])
     
     # check imprinting for a biallelic variant
     var = self.create_variant(position='150', cq='missense_variant',
         geno=['1/1', '0/1', '0/1'])
     self.inh = Autosomal([var], self.trio, inh, "TEST")
     self.assertEqual(self.inh.get_candidate_variants(), [])
Esempio n. 13
0
    def test_get_candidate_variants_compound_het(self):
        """ test that get_candidate_variants() works for biallelic variants
        """

        inh = {"inh": ["Biallelic"], "confirmed_status": ["confirmed dd gene"]}
        var1 = self.create_variant(position='150',
                                   cq='stop_gained',
                                   geno=['0/1', '0/1', '0/0'])
        var2 = self.create_variant(position='151',
                                   cq='stop_gained',
                                   geno=['0/1', '0/0', '1/0'])
        self.inh = Autosomal([var1, var2], self.trio, inh, "TEST")

        self.assertEqual(
            sorted(self.inh.get_candidate_variants()),
            sorted([(var1, ['compound_het'], ['Biallelic'], ['TEST']),
                    (var2, ['compound_het'], ['Biallelic'], ['TEST'])]))

        # check that a single variant isn't included in the compound hets
        self.inh = Autosomal([var1], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])
Esempio n. 14
0
    def test_is_compound_pair_proband_only(self):
        """ check that is_compound_pair() includes proband-only pairs
        """

        fam = Family("test")
        fam.add_child("child", 'dad_id', 'mom_id', 'F', '2', "child_vcf")
        fam.set_child()

        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1",
                                   position="150",
                                   sex="F",
                                   cq="stop_gained")
        var2 = self.create_variant(chrom="1",
                                   position="160",
                                   sex="F",
                                   cq="stop_gained")

        inh = Autosomal([var1, var2], fam, self.known_gene, "TEST")

        # check that a proband-only passes, regardless of the parental genotypes
        self.assertTrue(inh.is_compound_pair(var1, var2))
Esempio n. 15
0
    def setUp(self):
        """ define a family and variant, and start the Inheritance class
        """

        # generate a test family
        sex = "F"
        mom_aff = "1"
        dad_aff = "1"

        self.trio = self.create_family(sex, mom_aff, dad_aff)

        # generate list of variants
        self.variants = [self.create_variant(sex)]
        self.variants.append(self.create_variant(sex))

        # make sure we've got known genes data
        self.known_gene = {
            "inh": ["Monoallelic"],
            "confirmed_status": ["confirmed dd gene"]
        }

        self.inh = Autosomal(self.variants, self.trio, self.known_gene, "1001")
Esempio n. 16
0
    def find_variants(self, variants, gene):
        """ finds variants that fit inheritance models
        
        Args:
            variants: list of TrioGenotype objects
            gene: gene ID as string
        
        Returns:
            list of variants that pass inheritance checks
        """

        # get the inheritance for the gene (monoalleleic, biallelic, hemizygous
        # etc), but allow for times when we haven't specified a list of genes
        # to use
        gene_inh = None
        if self.known_genes is not None and gene in self.known_genes:
            gene_inh = self.known_genes[gene]["inh"]

        # ignore intergenic variants
        if gene is None:
            for var in variants:
                if var.get_chrom() == self.debug_chrom and var.get_position(
                ) == self.debug_pos:
                    print(var, "lacks HGNC/gene symbol")
            return []

        logging.debug(self.family.child.get_id() + " " + gene + " " + \
            str(variants) + " " + str(gene_inh))
        chrom_inheritance = variants[0].get_inheritance_type()

        if chrom_inheritance == "autosomal":
            finder = Autosomal(variants, self.family, self.known_genes,
                               gene_inh, self.cnv_regions)
        elif chrom_inheritance in ["XChrMale", "XChrFemale", "YChrMale"]:
            finder = Allosomal(variants, self.family, self.known_genes,
                               gene_inh, self.cnv_regions)

        return finder.get_candidate_variants()
Esempio n. 17
0
    def test_get_candidate_variants_monoallelic(self):
        """ test that get_candidate_variants() works for a monoallelic variant
        """

        inh = {
            "inh": ["Monoallelic"],
            "confirmed_status": ["confirmed dd gene"]
        }
        var = self.create_variant(position='150',
                                  cq='stop_gained',
                                  geno=['0/1', '0/0', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")

        self.assertEqual(
            self.inh.get_candidate_variants(),
            [(var, ['single_variant'], ['Monoallelic'], ['TEST'])])

        # check a variant that shouldn't pass the monoallelic route
        var = self.create_variant(position='150',
                                  cq='stop_gained',
                                  geno=['0/1', '0/1', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])
 def setUp(self):
     """ define a family and variant, and start the Inheritance class
     """
     
     # generate a test family
     sex = "F"
     mom_aff = "1"
     dad_aff = "1"
     
     self.trio = self.create_family(sex, mom_aff, dad_aff)
     
     # generate list of variants
     self.variants = [self.create_variant(sex)]
     self.variants.append(self.create_variant(sex))
     
     # make sure we've got known genes data
     self.known_gene = {"inh": ["Monoallelic"], "confirmed_status": ["confirmed dd gene"]}
     
     self.inh = Autosomal(self.variants, self.trio, self.known_gene, "1001")
 def setUp(self):
     """ define a family and variant, and start the Autosomal class
     """
     
     # generate a test family
     sex = "F"
     mom_aff = "1"
     dad_aff = "1"
     
     self.trio = self.create_family(sex, mom_aff, dad_aff)
     
     # generate a test variant
     child = create_snv(sex, "0/1")
     mom = create_snv("F", "0/0")
     dad = create_snv("M", "0/0")
     
     var = TrioGenotypes(child.get_chrom(), child.get_position(),child, mom, dad)
     self.variants = [var]
     
     # make sure we've got known genes data
     self.known_gene = {"inh": ["Monoallelic"], "confirmed_status": ["confirmed dd gene"]}
     
     self.inh = Autosomal(self.variants, self.trio, self.known_gene, "1001")
     self.inh.is_lof = var.child.is_lof()
 def test_check_compound_hets(self):
     """ test that check_compound_hets() works correctly for autosomal vars
     """
     
     # set some variants, so we can alter them later
     var1 = self.create_variant(chrom="1", position="150", sex="F", cq="stop_gained")
     var2 = self.create_variant(chrom="1", position="160", sex="F", cq="stop_gained")
     var3 = self.create_variant(chrom="1", position="170", sex="F", cq="stop_gained")
     
     # set the inheritance type, the compound het type ("compound_het"
     # for autosomal variants, and start autosomal inheritance)
     # known_genes = "Biallelic"
     known_gene = {"inh": ["Biallelic"], "confirmed_status": ["confirmed dd gene"]}
     self.inh = Autosomal([var1, var2, var3], self.trio, known_gene, "TEST")
     
     variants = [(), ()]
     
     # check the expected "110, 101" combo passes
     variants[0] = (self.set_compound_het_var(var1, "110"),)
     variants[1] = (self.set_compound_het_var(var2, "101"),)
     self.assertEqual(sorted(self.inh.check_compound_hets(variants)), sorted(variants))
     
     # check that > 2 valid compound hets passes all variants
     variants = [(), (), ()]
     variants[0] = (self.set_compound_het_var(var1, "110"),)
     variants[1] = (self.set_compound_het_var(var2, "101"),)
     variants[2] = (self.set_compound_het_var(var3, "110"),)
     self.assertEqual(sorted(self.inh.check_compound_hets(variants)), sorted(variants))
     
     # check that a single var fails to give compound hets
     single_var = variants[:1]
     self.assertEqual(self.inh.check_compound_hets(single_var), [])
     
     # check that zero length list gives no compound hets
     no_vars = []
     self.assertEqual(self.inh.check_compound_hets(no_vars), [])
class TestAutosomalPy(unittest.TestCase):
    """ test the Autosomal class
    """
    
    def setUp(self):
        """ define a family and variant, and start the Autosomal class
        """
        
        # generate a test family
        sex = "F"
        mom_aff = "1"
        dad_aff = "1"
        
        self.trio = self.create_family(sex, mom_aff, dad_aff)
        
        # generate a test variant
        child = create_snv(sex, "0/1")
        mom = create_snv("F", "0/0")
        dad = create_snv("M", "0/0")
        
        var = TrioGenotypes(child.get_chrom(), child.get_position(),child, mom, dad)
        self.variants = [var]
        
        # make sure we've got known genes data
        self.known_gene = {"inh": ["Monoallelic"], "confirmed_status": ["confirmed dd gene"]}
        
        self.inh = Autosomal(self.variants, self.trio, self.known_gene, "1001")
        self.inh.is_lof = var.child.is_lof()
    
    def create_family(self, child_gender, mom_aff, dad_aff):
        """ create a default family, with optional gender and parental statuses
        """
        
        fam = Family('test')
        fam.add_child('child', 'mother', 'father', child_gender, '2', 'child_vcf')
        fam.add_mother('mother', '0', '0', 'female', mom_aff, 'mother_vcf')
        fam.add_father('father', '0', '0', 'male', dad_aff, 'father_vcf')
        fam.set_child()
        
        return fam
    
    def set_trio_genos(self, var, geno):
        """ convenience function to set the trio genotypes for a variant
        """
        
        genos = {"0": "0/0", "1": "0/1", "2": "1/1"}
        
        # convert the geno codes to allele codes
        child = genos[geno[0]]
        mom = genos[geno[1]]
        dad = genos[geno[2]]
        
        # set the genotype field for each individual
        var.child.format["GT"] = child
        var.mother.format["GT"] = mom
        var.father.format["GT"] = dad
        
        # and set th genotype for each individual
        var.child.set_genotype()
        var.mother.set_genotype()
        var.father.set_genotype()
        
        # set the trio genotypes for the inheritance object
        self.inh.set_trio_genotypes(var)
    
    def test_check_variant_without_parents(self):
        """ test that check_variant_without_parents() works correctly
        """
        
        var = self.variants[0]
        self.set_trio_genos(var, "100")
        
        # remove the parents, so it appears the var lacks parental information
        self.inh.trio.mother = None
        self.inh.trio.father = None
        
        # check for monoallelic inheritance
        self.assertEqual(self.inh.check_variant_without_parents("Monoallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "autosomal without parents")
        
        # check for biallelic inheritance
        self.assertEqual(self.inh.check_variant_without_parents("Biallelic"), "compound_het")
        
        self.set_trio_genos(var, "200")
        self.assertEqual(self.inh.check_variant_without_parents("Monoallelic"), "nothing")
        self.assertEqual(self.inh.check_variant_without_parents("Biallelic"), "single_variant")
    
    def test_check_heterozygous_de_novo(self):
        """ test that check_heterozygous() works correctly for de novos
        """
        
        var = self.variants[0]
        self.inh.set_trio_genotypes(var)
        # check for monoallelic inheritance
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "de novo as single_variant")
        
        # mosaic should operate as per monoallelic
        self.assertEqual(self.inh.check_heterozygous("Mosaic"), "single_variant")
        
        # check for biallelic inheritance
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "de novo as compound_het")
        
        
        for geno in ["101", "102", "110", "112", "122"]:
            self.set_trio_genos(var, geno)
            self.inh.check_heterozygous("Monoallelic")
            self.assertNotEqual(self.inh.log_string, "de novo as single_variant")
        
    def test_check_heterozygous_affected_mother(self):
        """ test that check_heterozygous() works correctly for affected mothers
        """
        
        var = self.variants[0]
        
        # check that trio = 110, with het affected mother is captured
        self.set_trio_genos(var, "110")
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "transmitted from aff, other parent non-carrier or aff")
        
        # mosaic should operate as per monoallelic
        self.assertEqual(self.inh.check_heterozygous("Mosaic"), "single_variant")
        
        # check that when the other parent is also non-ref, the variant is no
        # longer captured, unless the parent is affected
        self.set_trio_genos(var, "111")
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "typically for trios with non-de novo unaffected parents")
        
        # mosaic should operate as per monoallelic
        self.assertEqual(self.inh.check_heterozygous("Mosaic"), "nothing")
        
        self.inh.father_affected = True
        self.inh.check_heterozygous("Monoallelic")
        self.assertEqual(self.inh.log_string, "transmitted from aff, other parent non-carrier or aff")
    
    def test_check_heterozygous_affected_father(self):
        """ test that check_heterozygous() works correctly for affected fathers
        """
        
        var = self.variants[0]
        # set the father as non-ref genotype and affected
        self.set_trio_genos(var, "101")
        self.inh.father_affected = True
        
        # check that the het proband, with het affected father is captured
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "transmitted from aff, other parent non-carrier or aff")
        
        # check that when the other parent is also non-ref, the variant is no
        # longer captured, unless the parent is affected
        self.set_trio_genos(var, "111")
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "typically for trios with non-de novo unaffected parents")
        
        self.inh.mother_affected = True
        self.inh.check_heterozygous("Monoallelic")
        self.assertEqual(self.inh.log_string, "transmitted from aff, other parent non-carrier or aff")
    
    def test_check_heterozygous_biallelic_non_ref_father(self):
        """ test that check_heterozygous() works correctly for biallelic genes
        """
        
        var = self.variants[0]
        # check for trio = 101
        self.set_trio_genos(var, "101")
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "het-check for recessive genes and unaff parents not homoz")
        
        # check that trio = 102, with affected father comes through other route
        self.set_trio_genos(var, "102")
        self.inh.father_affected = True
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "transmitted from aff, other parent non-carrier or aff")
        
        # check for trio = 102, without affected father
        self.inh.father_affected = False
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "typically for trios with non-de novo unaffected parents")
    
    def test_check_heterozygous_biallelic_non_ref_mother(self):
        """ test that check_heterozygous() works correctly for biallelic genes
        """
        
        # check for trio = 110
        var = self.variants[0]
        self.set_trio_genos(var, "110")
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "het-check for recessive genes and unaff parents not homoz")
        
        # check for trio = 120, with affected mother comes through other route
        var = self.variants[0]
        self.set_trio_genos(var, "120")
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "transmitted from aff, other parent non-carrier or aff")
        
        # check for trio = 120, without affected mother
        self.set_trio_genos(var, "120")
        self.inh.mother_affected = False
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "typically for trios with non-de novo unaffected parents")
    
    def test_check_heterozygous_biallelic_both_parents_non_ref(self):
        """ test that check_heterozygous() works correctly for biallelic genes
        """
        
        # check for trio = 111
        var = self.variants[0]
        self.set_trio_genos(var, "111")
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "het-check for recessive genes and unaff parents not homoz")
        
        # check for trio = 121 with affected mother, but unaffected father
        self.set_trio_genos(var, "121")
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "het-check for recessive genes and unaff parents not homoz")
        
        # check for trio = 112 with affected father, but unaffected mother
        self.set_trio_genos(var, "112")
        self.inh.mother_affected = False
        self.inh.father_affected = True
        
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "het-check for recessive genes and unaff parents not homoz")
    
    def test_check_homozygous(self):
        """ test that check_homozygous() works correctly
        """
        
        var = self.variants[0]
        
        # check for trio = 200, which is non-mendelian
        self.set_trio_genos(var, "200")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")
        
        # check for 201, which is non-mendelian
        self.set_trio_genos(var, "201")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")
        
        # check for 210, which is non-mendelian
        self.set_trio_genos(var, "210")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")
        
    def test_check_homozygous_with_cnv(self):
        """ test that check_homozygous() works correctly for variant lists with CNVs
        """
        
        # generate a test variant
        chrom = "1"
        position = "60000"
        child = create_cnv("F", "unknown", chrom=chrom, pos=position)
        mom = create_cnv("F", "unknown", chrom=chrom, pos=position)
        dad = create_cnv("M", "unknown", chrom=chrom, pos=position)
        
        cnv = TrioGenotypes(chrom, position, child, mom, dad)
        var = self.variants[0]
        
        # check for trio = 200, which is non-mendelian
        self.set_trio_genos(var, "200")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")
        
        # check when a CNV is in the variants list
        self.inh.variants.append(cnv)
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "non-mendelian, but CNV might affect call")
    
    def test_check_homozygous_biallelic(self):
        """ test that check_homozygous() works correctly for biallelic genes
        """
        
        var = self.variants[0]
        
        # check for trio = 211
        self.set_trio_genos(var, "211")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "both parents het in biallelic gene")
        
        # and check for trio = 221, but unaffected mother
        self.set_trio_genos(var, "221")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")
        
        # and check for trio = 221, with affected mother
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "homoz parent aff")
        
        # and check for trio = 222, with affected mother only, should fail
        self.set_trio_genos(var, "222")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")
        
        # and check for trio = 222, with both parents affected
        self.inh.father_affected = True
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "homoz parent aff")
        
        # and check for trio = 212, with affected father
        self.set_trio_genos(var, "212")
        self.inh.father_affected = True
        self.inh.mother_affected = False
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "homoz parent aff")
    
    def test_check_homozygous_monoallelic(self):
        """ test that check_homozygous() works correctly for monoallelic genes
        """
        
        var = self.variants[0]
        
        # check for trio = 211, without affected father
        self.set_trio_genos(var, "211")
        self.assertEqual(self.inh.check_homozygous("Monoallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")
        
        # check for trio = 211, with affected father only
        self.inh.father_affected = True
        self.assertEqual(self.inh.check_homozygous("Monoallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")
        
        # check for trio = 211, with both parents affected
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_homozygous("Monoallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "transmitted from affected parents")
Esempio n. 22
0
class TestAutosomalPy(unittest.TestCase):
    """ test the Autosomal class
    """
    def setUp(self):
        """ define a family and variant, and start the Autosomal class
        """

        # generate a test family
        child_gender = "F"
        mom_aff = "1"
        dad_aff = "1"

        self.trio = self.create_family(child_gender, mom_aff, dad_aff)

        # generate a test variant
        child_var = self.create_snv(child_gender, "0/1")
        mom_var = self.create_snv("F", "0/0")
        dad_var = self.create_snv("M", "0/0")

        var = TrioGenotypes(child_var)
        var.add_mother_variant(mom_var)
        var.add_father_variant(dad_var)
        self.variants = [var]

        # make sure we've got known genes data
        self.known_genes = {
            "TEST": {
                "inh": ["Monoallelic"],
                "confirmed_status": ["Confirmed DD Gene"]
            }
        }

        self.inh = Autosomal(self.variants, self.trio, self.known_genes,
                             "TEST")
        self.inh.is_lof = var.child.is_lof()

    def create_snv(self, gender, genotype):
        """ create a default variant
        """

        chrom = "1"
        pos = "15000000"
        snp_id = "."
        ref = "A"
        alt = "G"
        filt = "PASS"

        # set up a SNV object, since SNV inherits VcfInfo
        var = SNV(chrom, pos, snp_id, ref, alt, filt)

        info = "HGNC=TEST;CQ=missense_variant;random_tag"
        format_keys = "GT:DP"
        sample_values = genotype + ":50"

        var.add_info(info)
        var.add_format(format_keys, sample_values)
        var.set_gender(gender)
        var.set_genotype()

        return var

    def create_cnv(self, gender, inh, chrom, pos):
        """ create a default variant
        """

        snp_id = "."
        ref = "A"
        alt = "<DUP>"
        filt = "PASS"

        # set up a SNV object, since SNV inherits VcfInfo
        var = CNV(chrom, pos, snp_id, ref, alt, filt)

        info = "HGNC=TEST;HGNC_ALL=TEST;END=16000000;SVLEN=5000"
        format_keys = "INHERITANCE:DP"
        sample_values = inh + ":50"

        var.add_info(info)
        var.add_format(format_keys, sample_values)
        var.set_gender(gender)
        var.set_genotype()

        return var

    def create_family(self, child_gender, mom_aff, dad_aff):
        """ create a default family, with optional gender and parental statuses
        """

        fam = Family("test")
        fam.add_child("child", "child_vcf", "2", child_gender)
        fam.add_mother("mother", "mother_vcf", mom_aff, "2")
        fam.add_father("father", "father_vcf", dad_aff, "1")
        fam.set_child()

        return fam

    def set_trio_genos(self, var, geno):
        """ convenience function to set the trio genotypes for a variant
        """

        genos = {"0": "0/0", "1": "0/1", "2": "1/1"}

        # convert the geno codes to allele codes
        child = genos[geno[0]]
        mom = genos[geno[1]]
        dad = genos[geno[2]]

        # set the genotype field for each individual
        var.child.format["GT"] = child
        var.mother.format["GT"] = mom
        var.father.format["GT"] = dad

        # and set th genotype for each individual
        var.child.set_genotype()
        var.mother.set_genotype()
        var.father.set_genotype()

        # set the trio genotypes for the inheritance object
        self.inh.set_trio_genotypes(var)

    def test_check_variant_without_parents(self):
        """ test that check_variant_without_parents() works correctly
        """

        var = self.variants[0]
        self.set_trio_genos(var, "100")

        # remove the parents, so it appears the var lacks parental information
        self.inh.trio.mother = None
        self.inh.trio.father = None

        # check for monoallelic inheritance
        self.assertEqual(self.inh.check_variant_without_parents("Monoallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string, "autosomal without parents")

        # check for biallelic inheritance
        self.assertEqual(self.inh.check_variant_without_parents("Biallelic"),
                         "compound_het")

        self.set_trio_genos(var, "200")
        self.assertEqual(self.inh.check_variant_without_parents("Monoallelic"),
                         "nothing")
        self.assertEqual(self.inh.check_variant_without_parents("Biallelic"),
                         "single_variant")

    def test_check_heterozygous_de_novo(self):
        """ test that check_heterozygous() works correctly for de novos
        """

        var = self.variants[0]
        self.inh.set_trio_genotypes(var)
        # check for monoallelic inheritance
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string, "de novo as single_variant")

        # check for biallelic inheritance
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(self.inh.log_string, "de novo as compound_het")

        for geno in ["101", "102", "110", "112", "122"]:
            self.set_trio_genos(var, geno)
            self.inh.check_heterozygous("Monoallelic")
            self.assertNotEqual(self.inh.log_string,
                                "de novo as single_variant")

    def test_check_heterozygous_affected_mother(self):
        """ test that check_heterozygous() works correctly for affected mothers
        """

        var = self.variants[0]

        # check that trio = 110, with het affected mother is captured
        self.set_trio_genos(var, "110")
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"),
                         "single_variant")
        self.assertEqual(
            self.inh.log_string,
            "transmitted from aff, other parent non-carrier or aff")

        # check that when the other parent is also non-ref, the variant is no
        # longer captured, unless the parent is affected
        self.set_trio_genos(var, "111")
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "nothing")
        self.assertEqual(
            self.inh.log_string,
            "typically for trios with non-de novo unaffected parents")

        self.inh.father_affected = True
        self.inh.check_heterozygous("Monoallelic")
        self.assertEqual(
            self.inh.log_string,
            "transmitted from aff, other parent non-carrier or aff")

    def test_check_heterozygous_affected_father(self):
        """ test that check_heterozygous() works correctly for affected fathers
        """

        var = self.variants[0]
        # set the father as non-ref genotype and affected
        self.set_trio_genos(var, "101")
        self.inh.father_affected = True

        # check that the het proband, with het affected father is captured
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"),
                         "single_variant")
        self.assertEqual(
            self.inh.log_string,
            "transmitted from aff, other parent non-carrier or aff")

        # check that when the other parent is also non-ref, the variant is no
        # longer captured, unless the parent is affected
        self.set_trio_genos(var, "111")
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "nothing")
        self.assertEqual(
            self.inh.log_string,
            "typically for trios with non-de novo unaffected parents")

        self.inh.mother_affected = True
        self.inh.check_heterozygous("Monoallelic")
        self.assertEqual(
            self.inh.log_string,
            "transmitted from aff, other parent non-carrier or aff")

    def test_check_heterozygous_biallelic_non_ref_father(self):
        """ test that check_heterozygous() works correctly for biallelic genes
        """

        var = self.variants[0]
        # check for trio = 101
        self.set_trio_genos(var, "101")
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "het-check for recessive genes and unaff parents not homoz")

        # check that trio = 102, with affected father comes through other route
        self.set_trio_genos(var, "102")
        self.inh.father_affected = True
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "transmitted from aff, other parent non-carrier or aff")

        # check for trio = 102, without affected father
        self.inh.father_affected = False
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "nothing")
        self.assertEqual(
            self.inh.log_string,
            "typically for trios with non-de novo unaffected parents")

    def test_check_heterozygous_biallelic_non_ref_mother(self):
        """ test that check_heterozygous() works correctly for biallelic genes
        """

        # check for trio = 110
        var = self.variants[0]
        self.set_trio_genos(var, "110")
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "het-check for recessive genes and unaff parents not homoz")

        # check for trio = 120, with affected mother comes through other route
        var = self.variants[0]
        self.set_trio_genos(var, "120")
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "transmitted from aff, other parent non-carrier or aff")

        # check for trio = 120, without affected mother
        self.set_trio_genos(var, "120")
        self.inh.mother_affected = False
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "nothing")
        self.assertEqual(
            self.inh.log_string,
            "typically for trios with non-de novo unaffected parents")

    def test_check_heterozygous_biallelic_both_parents_non_ref(self):
        """ test that check_heterozygous() works correctly for biallelic genes
        """

        # check for trio = 111
        var = self.variants[0]
        self.set_trio_genos(var, "111")
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "het-check for recessive genes and unaff parents not homoz")

        # check for trio = 121 with affected mother, but unaffected father
        self.set_trio_genos(var, "121")
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "het-check for recessive genes and unaff parents not homoz")

        # check for trio = 112 with affected father, but unaffected mother
        self.set_trio_genos(var, "112")
        self.inh.mother_affected = False
        self.inh.father_affected = True

        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "het-check for recessive genes and unaff parents not homoz")

    def test_check_homozygous(self):
        """ test that check_homozygous() works correctly
        """

        var = self.variants[0]

        # check for trio = 200, which is non-mendelian
        self.set_trio_genos(var, "200")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")

        # check for 201, which is non-mendelian
        self.set_trio_genos(var, "201")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")

        # check for 210, which is non-mendelian
        self.set_trio_genos(var, "210")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")

    def test_check_homozygous_with_cnv(self):
        """ test that check_homozygous() works correctly for variant lists with CNVs
        """

        # generate a test variant
        chrom = "1"
        position = "60000"
        child_var = self.create_cnv("F", "unknown", chrom, position)
        mom_var = self.create_cnv("F", "unknown", chrom, position)
        dad_var = self.create_cnv("M", "unknown", chrom, position)

        cnv_var = TrioGenotypes(child_var)
        cnv_var.add_mother_variant(mom_var)
        cnv_var.add_father_variant(dad_var)

        var = self.variants[0]

        # check for trio = 200, which is non-mendelian
        self.set_trio_genos(var, "200")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")

        # check when a CNV is in the variants list
        self.inh.variants.append(cnv_var)
        self.assertEqual(self.inh.check_homozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(self.inh.log_string,
                         "non-mendelian, but CNV might affect call")

    def test_check_homozygous_biallelic(self):
        """ test that check_homozygous() works correctly for biallelic genes
        """

        var = self.variants[0]

        # check for trio = 211
        self.set_trio_genos(var, "211")
        self.assertEqual(self.inh.check_homozygous("Biallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string,
                         "both parents het in biallelic gene")

        # and check for trio = 221, but unaffected mother
        self.set_trio_genos(var, "221")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")

        # and check for trio = 221, with affected mother
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_homozygous("Biallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string, "homoz parent aff")

        # and check for trio = 222, with affected mother only, should fail
        self.set_trio_genos(var, "222")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")

        # and check for trio = 222, with both parents affected
        self.inh.father_affected = True
        self.assertEqual(self.inh.check_homozygous("Biallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string, "homoz parent aff")

        # and check for trio = 212, with affected father
        self.set_trio_genos(var, "212")
        self.inh.father_affected = True
        self.inh.mother_affected = False
        self.assertEqual(self.inh.check_homozygous("Biallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string, "homoz parent aff")

    def test_check_homozygous_monoallelic(self):
        """ test that check_homozygous() works correctly for monoallelic genes
        """

        var = self.variants[0]

        # check for trio = 211, without affected father
        self.set_trio_genos(var, "211")
        self.assertEqual(self.inh.check_homozygous("Monoallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")

        # check for trio = 211, with affected father only
        self.inh.father_affected = True
        self.assertEqual(self.inh.check_homozygous("Monoallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")

        # check for trio = 211, with both parents affected
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_homozygous("Monoallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string,
                         "transmitted from affected parents")
class TestInheritancePy(unittest.TestCase):
    """ test the Inheritance class
    """
    def setUp(self):
        """ define a family and variant, and start the Inheritance class
        """

        # generate a test family
        child_gender = "F"
        mom_aff = "1"
        dad_aff = "1"

        self.trio = self.create_family(child_gender, mom_aff, dad_aff)

        # generate list of variants
        self.variants = [self.create_variant(child_gender)]
        self.variants.append(self.create_variant(child_gender))

        # make sure we've got known genes data
        self.known_genes = {
            "TEST": {
                "inh": ["Monoallelic"],
                "confirmed_status": ["Confirmed DD Gene"]
            }
        }

        self.inh = Autosomal(self.variants, self.trio, self.known_genes,
                             "TEST")

    def create_snv(self, gender, genotype, chrom, pos, cq=None):
        """ create a default variant
        """

        snp_id = "."
        ref = "A"
        alt = "G"
        filt = "PASS"

        if cq is None:
            cq = "missense_variant"

        # set up a SNV object, since SNV inherits VcfInfo
        var = SNV(chrom, pos, snp_id, ref, alt, filt)

        info = "HGNC=TEST;CQ={};random_tag".format(cq)
        format_keys = "GT:DP"
        sample_values = genotype + ":50"

        var.add_info(info)
        var.add_format(format_keys, sample_values)
        var.set_gender(gender)
        var.set_genotype()

        return var

    def create_cnv(self, gender, inh, chrom, pos, cq=None):
        """ create a default variant
        """

        snp_id = "."
        ref = "A"
        alt = "<DEL>"
        filt = "PASS"

        if cq is None:
            cq = "transcript_ablation"

        # set up a SNV object, since SNV inherits VcfInfo
        var = CNV(chrom, pos, snp_id, ref, alt, filt)

        info = "CQ={};HGNC=TEST;HGNC_ALL=TEST;END=16000000;SVLEN=5000".format(
            cq)
        format_keys = "INHERITANCE:DP"
        sample_values = inh + ":50"

        var.add_info(info)
        var.add_format(format_keys, sample_values)
        var.set_gender(gender)
        var.set_genotype()

        return var

    def create_variant(self,
                       child_gender,
                       chrom="1",
                       position="15000000",
                       cq=None):
        """ creates a TrioGenotypes variant
        """

        # generate a test variant
        try:
            child_var = self.create_snv(child_gender, "0/1", chrom, position,
                                        cq)
        except ValueError:
            child_var = self.create_snv(child_gender, "1/1", chrom, position,
                                        cq)

        mom_var = self.create_snv("F", "0/0", chrom, position, cq)
        dad_var = self.create_snv("M", "0/0", chrom, position, cq)

        var = TrioGenotypes(child_var)
        var.add_mother_variant(mom_var)
        var.add_father_variant(dad_var)

        return var

    def create_family(self, child_gender, mom_aff, dad_aff):
        """ create a default family, with optional gender and parental statuses
        """

        fam = Family("test")
        fam.add_child("child", "child_vcf", "2", child_gender)
        fam.add_mother("mother", "mother_vcf", mom_aff, "2")
        fam.add_father("father", "father_vcf", dad_aff, "1")
        fam.set_child()

        return fam

    def test_check_inheritance_mode_matches_gene_mode(self):
        """ test that check_inheritance_mode_matches_gene_mode() works correctly
        """

        # check that the default inheritance types have been set up correctly
        self.assertEqual(self.inh.inheritance_modes,
                         {"Monoallelic", "Biallelic", "Both"})

        # make sure that the default var and gene inheritance work
        self.assertTrue(self.inh.check_inheritance_mode_matches_gene_mode())

        # check that no gene inheritance overlap fails
        self.inh.gene_inheritance = {"Mosaic"}
        self.inh.inheritance_modes = {"Monoallelic", "Biallelic", "Both"}
        self.assertFalse(self.inh.check_inheritance_mode_matches_gene_mode())

        # check that a single inheritance type still works
        self.inh.gene_inheritance = {"Monoallelic"}
        self.assertTrue(self.inh.check_inheritance_mode_matches_gene_mode())

        # check that multiple inheritance types for a gene still work
        self.inh.gene_inheritance = {"Monoallelic", "Biallelic"}
        self.assertTrue(self.inh.check_inheritance_mode_matches_gene_mode())

        # check that extra inheritance modes are included still work
        self.inh.gene_inheritance = {"Monoallelic", "Biallelic", "Mosaic"}
        self.assertTrue(self.inh.check_inheritance_mode_matches_gene_mode())

    def test_set_trio_genotypes(self):
        """ test that set_trio_genotypes() works correctly
        """

        # set the genotypes using the default variant
        var = self.variants[0]
        self.inh.set_trio_genotypes(var)

        # the genotypes for the inh object should match the vars genotypes
        self.assertEqual(self.inh.child, var.child)
        self.assertEqual(self.inh.mom, var.mother)
        self.assertEqual(self.inh.dad, var.father)

        # now remove the parents before re-setting the genotypes
        del var.mother
        del var.father
        self.inh.trio.father = None
        self.inh.trio.mother = None
        self.inh.set_trio_genotypes(var)

        # the child should match the vars genotypes, but the parent's
        # genotypes should be None
        self.assertEqual(self.inh.child, var.child)
        self.assertIsNone(self.inh.mom)
        self.assertIsNone(self.inh.dad)

    def test_add_variant_to_appropriate_list(self):
        """ test that add_variant_to_appropriate_list() works correctly
        """

        var = self.variants[0]
        inheritance = "Monoallelic"
        check = "compound_het"

        # check that compound_het vars are only added to the compound_het list
        self.inh.compound_hets = []
        self.inh.candidates = []
        self.inh.add_variant_to_appropriate_list(var, check, inheritance)
        self.assertEqual(self.inh.candidates, [])
        self.assertEqual(self.inh.compound_hets,
                         [(var, (check, ), (inheritance, ))])

        # check that single_variant vars are only added to the candidates list
        self.inh.compound_hets = []
        self.inh.candidates = []
        check = "single_variant"
        self.inh.add_variant_to_appropriate_list(var, check, inheritance)
        self.assertEqual(self.inh.candidates, [(var, [check], [inheritance])])
        self.assertEqual(self.inh.compound_hets, [])

        # check that other vars aren't added either list
        self.inh.compound_hets = []
        self.inh.candidates = []
        check = "nothing"
        self.inh.add_variant_to_appropriate_list(var, check, inheritance)
        self.assertEqual(self.inh.candidates, [])
        self.assertEqual(self.inh.compound_hets, [])

    def test_check_if_any_variant_is_cnv(self):
        """ test if check_if_any_variant_is_cnv() works correctly
        """

        # generate a test variant
        chrom = "1"
        position = "60000"
        child_var = self.create_cnv("F", "unknown", chrom, position)
        mom_var = self.create_cnv("F", "unknown", chrom, position)
        dad_var = self.create_cnv("M", "unknown", chrom, position)

        cnv_var = TrioGenotypes(child_var)
        cnv_var.add_mother_variant(mom_var)
        cnv_var.add_father_variant(dad_var)

        # check that all variants=SNV returns False
        self.assertFalse(self.inh.check_if_any_variant_is_cnv())

        # add a CNV to the variants, then check that we find a CNV
        self.inh.variants.append(cnv_var)
        self.assertTrue(self.inh.check_if_any_variant_is_cnv())

    def set_compound_het_var(self, var, geno):
        """ convenience function to set the trio genotypes for a variant
        """

        genos = {"0": "0/0", "1": "0/1", "2": "1/1"}

        # convert the geno codes to allele codes
        child = genos[geno[0]]
        mom = genos[geno[1]]
        dad = genos[geno[2]]

        # set the genotype field for each individual
        var.child.format["GT"] = child
        var.mother.format["GT"] = mom
        var.father.format["GT"] = dad

        # and set th genotype for each individual
        var.child.set_genotype()
        var.mother.set_genotype()
        var.father.set_genotype()

        # set the trio genotypes for the inheritance object
        return var

    def test_check_compound_hets(self):
        """ test that check_compound_hets() works correctly for autosomal vars
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant("F",
                                   chrom="1",
                                   position="15000000",
                                   cq="stop_gained")
        var2 = self.create_variant("F",
                                   chrom="1",
                                   position="16000000",
                                   cq="stop_gained")
        var3 = self.create_variant("F",
                                   chrom="1",
                                   position="17000000",
                                   cq="stop_gained")

        # set the inheritance type, the compound het type ("compound_het"
        # for autosomal variants, and start autosomal inheritance)
        # known_genes = "Biallelic"
        known_genes = {
            "TEST": {
                "inh": ["Biallelic"],
                "confirmed_status": ["Confirmed DD Gene"]
            }
        }
        self.inh = Autosomal([var1, var2, var3], self.trio, known_genes,
                             "TEST")

        variants = [(), ()]

        # check the expected "110, 101" combo passes
        variants[0] = (self.set_compound_het_var(var1, "110"), )
        variants[1] = (self.set_compound_het_var(var2, "101"), )
        self.assertEqual(sorted(self.inh.check_compound_hets(variants)),
                         sorted(variants))

        # check that > 2 valid compound hets passes all variants
        variants = [(), (), ()]
        variants[0] = (self.set_compound_het_var(var1, "110"), )
        variants[1] = (self.set_compound_het_var(var2, "101"), )
        variants[2] = (self.set_compound_het_var(var3, "110"), )
        self.assertEqual(sorted(self.inh.check_compound_hets(variants)),
                         sorted(variants))

        # check that a single var fails to give compound hets
        single_var = variants[:1]
        self.assertEqual(self.inh.check_compound_hets(single_var), [])

        # check that zero length list gives no compound hets
        no_vars = []
        self.assertEqual(self.inh.check_compound_hets(no_vars), [])

    def test_is_compound_pair_identical_variants(self):
        """ check that is_compound_pair() excludes compound pairs where the
        members are identical
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant("F",
                                   chrom="1",
                                   position="150",
                                   cq="stop_gained")
        var2 = self.create_variant("F",
                                   chrom="1",
                                   position="160",
                                   cq="stop_gained")

        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")

        # don't include pairs where the first and the second variant are identical
        self.assertFalse(self.inh.is_compound_pair(var1, var1))

        # make sure it works normally
        self.assertTrue(self.inh.is_compound_pair(var1, var2))

    def test_is_compound_pair_both_missense_with_parents(self):
        """check that is_compound_pair() excludes pairs where both are missense
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant("F",
                                   chrom="1",
                                   position="150",
                                   cq="missense_variant")
        var2 = self.create_variant("F",
                                   chrom="1",
                                   position="160",
                                   cq="missense_variant")
        var3 = self.create_variant("F",
                                   chrom="1",
                                   position="160",
                                   cq="inframe_deletion")
        var4 = self.create_variant("F",
                                   chrom="1",
                                   position="160",
                                   cq="stop_gained")

        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")
        var3 = self.set_compound_het_var(var3, "101")
        var4 = self.set_compound_het_var(var4, "101")

        # dont exclude pairs where both members are not loss-of-function if the
        # proband has parents
        self.assertTrue(self.inh.is_compound_pair(var1, var2))
        self.assertTrue(self.inh.is_compound_pair(var1, var3))

        # make sure it works normally
        self.assertTrue(self.inh.is_compound_pair(var1, var4))

    def test_is_compound_pair_both_missense_without_parents(self):
        """check that is_compound_pair() excludes pairs where both are missense
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant("F",
                                   chrom="1",
                                   position="150",
                                   cq="missense_variant")
        var2 = self.create_variant("F",
                                   chrom="1",
                                   position="160",
                                   cq="missense_variant")
        var3 = self.create_variant("F",
                                   chrom="1",
                                   position="160",
                                   cq="inframe_deletion")
        var4 = self.create_variant("F",
                                   chrom="1",
                                   position="160",
                                   cq="stop_gained")

        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")
        var3 = self.set_compound_het_var(var3, "101")
        var4 = self.set_compound_het_var(var4, "101")

        # drop the parents
        self.inh.trio.father = None
        self.inh.trio.mother = None

        # exclude pairs where both members are not loss-of-function
        self.assertFalse(self.inh.is_compound_pair(var1, var2))
        self.assertFalse(self.inh.is_compound_pair(var1, var3))

        # make sure it works if one variant is loss-of-function
        self.assertTrue(self.inh.is_compound_pair(var1, var4))

    def test_is_compound_pair_unknown_gene(self):
        """check that is_compound_pair() excludes pairs for unknown genes
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant("F",
                                   chrom="1",
                                   position="150",
                                   cq="stop_gained")
        var2 = self.create_variant("F",
                                   chrom="1",
                                   position="160",
                                   cq="stop_gained")

        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")

        var1.child.genes = ["."]
        var2.child.genes = ["."]

        # exclude pairs where both members are not loss-of-function
        self.assertFalse(self.inh.is_compound_pair(var1, var2))

    def test_is_compound_pair_cnv(self):
        """ check that is_compound_pair() includes pairs with CNVs
        """

        # generate a test variant
        chrom = "1"
        position = "60000"
        child_var = self.create_cnv("F", "unknown", chrom, position)
        mom_var = self.create_cnv("F", "unknown", chrom, position)
        dad_var = self.create_cnv("M", "unknown", chrom, position)

        cnv = TrioGenotypes(child_var)
        cnv.add_mother_variant(mom_var)
        cnv.add_father_variant(dad_var)

        # set some variants, so we can alter them later
        snv = self.create_variant("F",
                                  chrom="1",
                                  position="150",
                                  cq="stop_gained")
        snv = self.set_compound_het_var(snv, "110")

        # exclude pairs where both members are not loss-of-function
        self.assertTrue(self.inh.is_compound_pair(cnv, snv))

    def test_is_compound_pair_proband_only(self):
        """ check that is_compound_pair() includes proband-only pairs
        """

        fam = Family("test")
        fam.add_child("child", "child_vcf", "2", "F")
        fam.set_child()

        # set some variants, so we can alter them later
        var1 = self.create_variant("F",
                                   chrom="1",
                                   position="150",
                                   cq="stop_gained")
        var2 = self.create_variant("F",
                                   chrom="1",
                                   position="160",
                                   cq="stop_gained")

        inh = Autosomal([var1, var2], fam, self.known_genes, "TEST")

        # check that a proband-only passes, regardless of the parental genotypes
        self.assertTrue(inh.is_compound_pair(var1, var2))

    def test_is_compound_pair_allosomal(self):
        """ check that is_compound_pair() works when the father is affected
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant("M",
                                   chrom="X",
                                   position="150",
                                   cq="stop_gained")
        var2 = self.create_variant("M",
                                   chrom="X",
                                   position="160",
                                   cq="stop_gained")

        var1 = self.set_compound_het_var(var1, "210")
        var2 = self.set_compound_het_var(var2, "202")

        # check when the father is unaffected
        self.assertFalse(self.inh.is_compound_pair(var1, var2))

        # now check when the father is affected
        self.inh.father_affected = True
        self.assertTrue(self.inh.is_compound_pair(var1, var2))

        # make sure we can't set the father as het on the X chrom
        with self.assertRaises(ValueError):
            self.set_compound_het_var(var2, "201")

    def test_is_compound_pair_genotype_combinations(self):
        """ check the various genotype combinations for a compound het
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant("M",
                                   chrom="1",
                                   position="150",
                                   cq="stop_gained")
        var2 = self.create_variant("M",
                                   chrom="1",
                                   position="160",
                                   cq="stop_gained")

        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")

        # check that the expected scenario passes
        self.assertTrue(self.inh.is_compound_pair(var1, var2))

        # check that compound hets with de novos fail
        var1 = self.set_compound_het_var(var1, "100")
        var2 = self.set_compound_het_var(var2, "101")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))

        # check that compound hets have to be transmitted from both parents
        var1 = self.set_compound_het_var(var1, "101")
        var2 = self.set_compound_het_var(var2, "101")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))

        # check that compound hets have to be transmitted from both parents
        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "110")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))

        # make sure that only compound hets in trans pass. We exclude
        var1 = self.set_compound_het_var(var1, "111")
        var2 = self.set_compound_het_var(var2, "101")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))

        var1 = self.set_compound_het_var(var1, "111")
        var2 = self.set_compound_het_var(var2, "111")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))
class TestAutosomalPy(unittest.TestCase):
    """ test the Autosomal class
    """
    def setUp(self):
        """ define a family and variant, and start the Autosomal class
        """

        # generate a test family
        sex = "F"
        mom_aff = "1"
        dad_aff = "1"

        self.trio = self.create_family(sex, mom_aff, dad_aff)

        # generate a test variant
        child = create_snv(sex, "0/1")
        mom = create_snv("F", "0/0")
        dad = create_snv("M", "0/0")

        var = TrioGenotypes(child.get_chrom(), child.get_position(), child,
                            mom, dad)
        self.variants = [var]

        # make sure we've got known genes data
        self.known_gene = {
            "inh": ["Monoallelic"],
            "confirmed_status": ["confirmed dd gene"]
        }

        self.inh = Autosomal(self.variants, self.trio, self.known_gene, "1001")
        self.inh.is_lof = var.child.is_lof()

    def create_family(self, child_gender, mom_aff, dad_aff):
        """ create a default family, with optional gender and parental statuses
        """

        fam = Family('test')
        fam.add_child('child', 'mother', 'father', child_gender, '2',
                      'child_vcf')
        fam.add_mother('mother', '0', '0', 'female', mom_aff, 'mother_vcf')
        fam.add_father('father', '0', '0', 'male', dad_aff, 'father_vcf')
        fam.set_child()

        return fam

    def set_trio_genos(self, var, geno):
        """ convenience function to set the trio genotypes for a variant
        """

        genos = {"0": "0/0", "1": "0/1", "2": "1/1"}

        # convert the geno codes to allele codes
        child = genos[geno[0]]
        mom = genos[geno[1]]
        dad = genos[geno[2]]

        # set the genotype field for each individual
        var.child.format["GT"] = child
        var.mother.format["GT"] = mom
        var.father.format["GT"] = dad

        # and set th genotype for each individual
        var.child.set_genotype()
        var.mother.set_genotype()
        var.father.set_genotype()

        # set the trio genotypes for the inheritance object
        self.inh.set_trio_genotypes(var)

    def test_check_variant_without_parents(self):
        """ test that check_variant_without_parents() works correctly
        """

        var = self.variants[0]
        self.set_trio_genos(var, "100")

        # remove the parents, so it appears the var lacks parental information
        self.inh.trio.mother = None
        self.inh.trio.father = None

        # check for monoallelic inheritance
        self.assertEqual(self.inh.check_variant_without_parents("Monoallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string, "autosomal without parents")

        # check for biallelic inheritance
        self.assertEqual(self.inh.check_variant_without_parents("Biallelic"),
                         "compound_het")

        self.set_trio_genos(var, "200")
        self.assertEqual(self.inh.check_variant_without_parents("Monoallelic"),
                         "nothing")
        self.assertEqual(self.inh.check_variant_without_parents("Biallelic"),
                         "single_variant")

    def test_check_heterozygous_de_novo(self):
        """ test that check_heterozygous() works correctly for de novos
        """

        var = self.variants[0]
        self.inh.set_trio_genotypes(var)
        # check for monoallelic inheritance
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string, "de novo as single_variant")

        # mosaic should operate as per monoallelic
        self.assertEqual(self.inh.check_heterozygous("Mosaic"),
                         "single_variant")

        # check for biallelic inheritance
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(self.inh.log_string, "de novo as compound_het")

        for geno in ["101", "102", "110", "112", "122"]:
            self.set_trio_genos(var, geno)
            self.inh.check_heterozygous("Monoallelic")
            self.assertNotEqual(self.inh.log_string,
                                "de novo as single_variant")

    def test_check_heterozygous_affected_mother(self):
        """ test that check_heterozygous() works correctly for affected mothers
        """

        var = self.variants[0]

        # check that trio = 110, with het affected mother is captured
        self.set_trio_genos(var, "110")
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"),
                         "single_variant")
        self.assertEqual(
            self.inh.log_string,
            "transmitted from aff, other parent non-carrier or aff")

        # mosaic should operate as per monoallelic
        self.assertEqual(self.inh.check_heterozygous("Mosaic"),
                         "single_variant")

        # check that when the other parent is also non-ref, the variant is no
        # longer captured, unless the parent is affected
        self.set_trio_genos(var, "111")
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "nothing")
        self.assertEqual(
            self.inh.log_string,
            "typically for trios with non-de novo unaffected parents")

        # mosaic should operate as per monoallelic
        self.assertEqual(self.inh.check_heterozygous("Mosaic"), "nothing")

        self.inh.father_affected = True
        self.inh.check_heterozygous("Monoallelic")
        self.assertEqual(
            self.inh.log_string,
            "transmitted from aff, other parent non-carrier or aff")

    def test_check_heterozygous_affected_father(self):
        """ test that check_heterozygous() works correctly for affected fathers
        """

        var = self.variants[0]
        # set the father as non-ref genotype and affected
        self.set_trio_genos(var, "101")
        self.inh.father_affected = True

        # check that the het proband, with het affected father is captured
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"),
                         "single_variant")
        self.assertEqual(
            self.inh.log_string,
            "transmitted from aff, other parent non-carrier or aff")

        # check that when the other parent is also non-ref, the variant is no
        # longer captured, unless the parent is affected
        self.set_trio_genos(var, "111")
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "nothing")
        self.assertEqual(
            self.inh.log_string,
            "typically for trios with non-de novo unaffected parents")

        self.inh.mother_affected = True
        self.inh.check_heterozygous("Monoallelic")
        self.assertEqual(
            self.inh.log_string,
            "transmitted from aff, other parent non-carrier or aff")

    def test_check_heterozygous_biallelic_non_ref_father(self):
        """ test that check_heterozygous() works correctly for biallelic genes
        """

        var = self.variants[0]
        # check for trio = 101
        self.set_trio_genos(var, "101")
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "het-check for recessive genes and unaff parents not homoz")

        # check that trio = 102, with affected father comes through other route
        self.set_trio_genos(var, "102")
        self.inh.father_affected = True
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "transmitted from aff, other parent non-carrier or aff")

        # check for trio = 102, without affected father
        self.inh.father_affected = False
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "nothing")
        self.assertEqual(
            self.inh.log_string,
            "typically for trios with non-de novo unaffected parents")

    def test_check_heterozygous_biallelic_non_ref_mother(self):
        """ test that check_heterozygous() works correctly for biallelic genes
        """

        # check for trio = 110
        var = self.variants[0]
        self.set_trio_genos(var, "110")
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "het-check for recessive genes and unaff parents not homoz")

        # check for trio = 120, with affected mother comes through other route
        var = self.variants[0]
        self.set_trio_genos(var, "120")
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "transmitted from aff, other parent non-carrier or aff")

        # check for trio = 120, without affected mother
        self.set_trio_genos(var, "120")
        self.inh.mother_affected = False
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "nothing")
        self.assertEqual(
            self.inh.log_string,
            "typically for trios with non-de novo unaffected parents")

    def test_check_heterozygous_biallelic_both_parents_non_ref(self):
        """ test that check_heterozygous() works correctly for biallelic genes
        """

        # check for trio = 111
        var = self.variants[0]
        self.set_trio_genos(var, "111")
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "het-check for recessive genes and unaff parents not homoz")

        # check for trio = 121 with affected mother, but unaffected father
        self.set_trio_genos(var, "121")
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "het-check for recessive genes and unaff parents not homoz")

        # check for trio = 112 with affected father, but unaffected mother
        self.set_trio_genos(var, "112")
        self.inh.mother_affected = False
        self.inh.father_affected = True

        self.assertEqual(self.inh.check_heterozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(
            self.inh.log_string,
            "het-check for recessive genes and unaff parents not homoz")

    def test_check_homozygous(self):
        """ test that check_homozygous() works correctly
        """

        var = self.variants[0]

        # check for trio = 200, which is non-mendelian
        self.set_trio_genos(var, "200")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")

        # check for 201, which is non-mendelian
        self.set_trio_genos(var, "201")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")

        # check for 210, which is non-mendelian
        self.set_trio_genos(var, "210")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")

    def test_check_homozygous_with_cnv(self):
        """ test that check_homozygous() works correctly for variant lists with CNVs
        """

        # generate a test variant
        chrom = "1"
        position = "60000"
        child = create_cnv("F", "unknown", chrom=chrom, pos=position)
        mom = create_cnv("F", "unknown", chrom=chrom, pos=position)
        dad = create_cnv("M", "unknown", chrom=chrom, pos=position)

        cnv = TrioGenotypes(chrom, position, child, mom, dad)
        var = self.variants[0]

        # check for trio = 200, which is non-mendelian
        self.set_trio_genos(var, "200")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")

        # check when a CNV is in the variants list
        self.inh.variants.append(cnv)
        self.assertEqual(self.inh.check_homozygous("Biallelic"),
                         "compound_het")
        self.assertEqual(self.inh.log_string,
                         "non-mendelian, but CNV might affect call")

    def test_check_homozygous_biallelic(self):
        """ test that check_homozygous() works correctly for biallelic genes
        """

        var = self.variants[0]

        # check for trio = 211
        self.set_trio_genos(var, "211")
        self.assertEqual(self.inh.check_homozygous("Biallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string,
                         "both parents het in biallelic gene")

        # and check for trio = 221, but unaffected mother
        self.set_trio_genos(var, "221")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")

        # and check for trio = 221, with affected mother
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_homozygous("Biallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string, "homoz parent aff")

        # and check for trio = 222, with affected mother only, should fail
        self.set_trio_genos(var, "222")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")

        # and check for trio = 222, with both parents affected
        self.inh.father_affected = True
        self.assertEqual(self.inh.check_homozygous("Biallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string, "homoz parent aff")

        # and check for trio = 212, with affected father
        self.set_trio_genos(var, "212")
        self.inh.father_affected = True
        self.inh.mother_affected = False
        self.assertEqual(self.inh.check_homozygous("Biallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string, "homoz parent aff")

    def test_check_homozygous_monoallelic(self):
        """ test that check_homozygous() works correctly for monoallelic genes
        """

        var = self.variants[0]

        # check for trio = 211, without affected father
        self.set_trio_genos(var, "211")
        self.assertEqual(self.inh.check_homozygous("Monoallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")

        # check for trio = 211, with affected father only
        self.inh.father_affected = True
        self.assertEqual(self.inh.check_homozygous("Monoallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")

        # check for trio = 211, with both parents affected
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_homozygous("Monoallelic"),
                         "single_variant")
        self.assertEqual(self.inh.log_string,
                         "transmitted from affected parents")
Esempio n. 25
0
    def test_check_compound_hets_autosomal(self):
        """ test that check_compound_hets() works correctly for autosomal vars
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant("F", chrom="1", position="15000000")
        var2 = self.create_variant("F", chrom="1", position="16000000")
        var3 = self.create_variant("F", chrom="1", position="17000000")

        # set the inheritance type, the compound het type ("compound_het"
        # for autosomal variants, and start autosomal inheritance)
        inh = "Biallelic"
        compound = "compound_het"
        self.inh = Autosomal([var1, var2, var3], self.trio, inh)

        variants = ["", ""]

        # check the expected "110, 101" combo passes
        variants[0] = self.set_compound_het_var(var1, "110", compound)
        variants[1] = self.set_compound_het_var(var2, "101", compound)
        if IS_PYTHON3:
            self.assertCountEqual(self.inh.check_compound_hets(variants),
                                  variants)
        elif IS_PYTHON2:
            self.assertEqual(sorted(self.inh.check_compound_hets(variants)),
                             sorted(variants))

        # check that "110, 110" combo fails
        variants[0] = self.set_compound_het_var(var1, "110", compound)
        variants[1] = self.set_compound_het_var(var2, "110", compound)
        self.assertEqual(self.inh.check_compound_hets(variants), [])

        # check that "101, 101" combo fails
        variants[0] = self.set_compound_het_var(var1, "101", compound)
        variants[1] = self.set_compound_het_var(var2, "101", compound)
        self.assertEqual(self.inh.check_compound_hets(variants), [])

        # check that > 2 valid compound hets passes all variants
        variants = ["", "", ""]
        variants[0] = self.set_compound_het_var(var1, "110", compound)
        variants[1] = self.set_compound_het_var(var2, "101", compound)
        variants[2] = self.set_compound_het_var(var3, "110", compound)
        if IS_PYTHON3:
            self.assertCountEqual(self.inh.check_compound_hets(variants),
                                  variants)
        elif IS_PYTHON2:
            self.assertEqual(sorted(self.inh.check_compound_hets(variants)),
                             sorted(variants))

        # check that a single var fails to give compound hets
        single_var = variants[:1]
        self.assertEqual(self.inh.check_compound_hets(single_var), [])

        # check that zero length list gives no compound hets
        no_vars = []
        self.assertEqual(self.inh.check_compound_hets(no_vars), [])

        # check that de novo containing "110, 100" combos give compound hets
        variants = ["", ""]
        variants[0] = self.set_compound_het_var(var1, "110", compound)
        variants[1] = self.set_compound_het_var(var2, "100", compound)
        if IS_PYTHON3:
            self.assertCountEqual(self.inh.check_compound_hets(variants),
                                  variants)
        elif IS_PYTHON2:
            self.assertEqual(sorted(self.inh.check_compound_hets(variants)),
                             sorted(variants))

        # check that de novo "100, 100" combos give compound hets
        variants[0] = self.set_compound_het_var(var1, "100", compound)
        variants[1] = self.set_compound_het_var(var2, "100", compound)
        if IS_PYTHON3:
            self.assertCountEqual(self.inh.check_compound_hets(variants),
                                  variants)
        elif IS_PYTHON2:
            self.assertEqual(sorted(self.inh.check_compound_hets(variants)),
                             sorted(variants))

        # check that "111, 111" combos require affected parents
        variants[0] = self.set_compound_het_var(var1, "111", compound)
        variants[1] = self.set_compound_het_var(var2, "111", compound)
        self.assertEqual(self.inh.check_compound_hets(variants), [])

        # check "111, 111" combo with a single affected parent
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_compound_hets(variants), [])

        # check "111, 111" combo with both parents affected
        self.inh.father_affected = True
        if IS_PYTHON3:
            self.assertCountEqual(self.inh.check_compound_hets(variants),
                                  variants)
        elif IS_PYTHON2:
            self.assertEqual(sorted(self.inh.check_compound_hets(variants)),
                             sorted(variants))

        # check that without parents, all variants are included, even if they
        # wouldn't pass normally
        self.inh.trio.mother = None
        self.inh.trio.father = None
        variants[0] = self.set_compound_het_var(var1, "101", compound)
        variants[1] = self.set_compound_het_var(var2, "101", compound)
        if IS_PYTHON3:
            self.assertCountEqual(self.inh.check_compound_hets(variants),
                                  variants)
        elif IS_PYTHON2:
            self.assertEqual(sorted(self.inh.check_compound_hets(variants)),
                             sorted(variants))
Esempio n. 26
0
class TestInheritancePy(unittest.TestCase):
    """ test the Inheritance class
    """
    def setUp(self):
        """ define a family and variant, and start the Inheritance class
        """

        # generate a test family
        sex = "F"
        mom_aff = "1"
        dad_aff = "1"

        self.trio = self.create_family(sex, mom_aff, dad_aff)

        # generate list of variants
        self.variants = [self.create_variant(sex)]
        self.variants.append(self.create_variant(sex))

        # make sure we've got known genes data
        self.known_gene = {
            "inh": ["Monoallelic"],
            "confirmed_status": ["confirmed dd gene"]
        }

        self.inh = Autosomal(self.variants, self.trio, self.known_gene, "1001")

    def create_variant(self,
                       chrom="1",
                       position="150",
                       sex='F',
                       cq=None,
                       geno=['0/1', '0/0', '0/0']):
        """ creates a TrioGenotypes variant
        """

        # generate a test variant
        child = create_snv(sex, geno[0], cq, chrom=chrom, pos=position)
        mom = create_snv("F", geno[1], cq, chrom=chrom, pos=position)
        dad = create_snv("M", geno[2], cq, chrom=chrom, pos=position)

        return TrioGenotypes(chrom, position, child, mom, dad)

    def create_family(self, child_gender, mom_aff, dad_aff):
        """ create a default family, with optional gender and parental statuses
        """

        fam = Family('test')
        fam.add_child('child', 'mother', 'father', child_gender, '2',
                      'child_vcf')
        fam.add_mother('mother', '0', '0', 'female', mom_aff, 'mother_vcf')
        fam.add_father('father', '0', '0', 'male', dad_aff, 'father_vcf')
        fam.set_child()

        return fam

    def test_check_inheritance_mode_matches_gene_mode(self):
        """ test that check_inheritance_mode_matches_gene_mode() works correctly
        """

        # check that the default inheritance types have been set up correctly
        self.assertEqual(
            self.inh.inheritance_modes,
            {"Monoallelic", "Biallelic", "Both", 'Imprinted', 'Mosaic'})

        # make sure that the default var and gene inheritance work
        self.assertTrue(self.inh.check_inheritance_mode_matches_gene_mode())

        # check that no gene inheritance overlap fails
        self.inh.gene_inheritance = {"Mosaic"}
        self.inh.inheritance_modes = {
            "Monoallelic", "Biallelic", "Both", 'Imprinted'
        }
        self.assertFalse(self.inh.check_inheritance_mode_matches_gene_mode())

        # check that a single inheritance type still works
        self.inh.gene_inheritance = {"Monoallelic"}
        self.assertTrue(self.inh.check_inheritance_mode_matches_gene_mode())

        # check that multiple inheritance types for a gene still work
        self.inh.gene_inheritance = {"Monoallelic", "Biallelic"}
        self.assertTrue(self.inh.check_inheritance_mode_matches_gene_mode())

        # check that extra inheritance modes are included still work
        self.inh.gene_inheritance = {"Monoallelic", "Biallelic", "Mosaic"}
        self.assertTrue(self.inh.check_inheritance_mode_matches_gene_mode())

    def test_set_trio_genotypes(self):
        """ test that set_trio_genotypes() works correctly
        """

        # set the genotypes using the default variant
        var = self.variants[0]
        self.inh.set_trio_genotypes(var)

        # the genotypes for the inh object should match the vars genotypes
        self.assertEqual(self.inh.child, var.child)
        self.assertEqual(self.inh.mom, var.mother)
        self.assertEqual(self.inh.dad, var.father)

        # now remove the parents before re-setting the genotypes
        del var.mother
        del var.father
        self.inh.trio.father = None
        self.inh.trio.mother = None
        self.inh.set_trio_genotypes(var)

        # the child should match the vars genotypes, but the parent's
        # genotypes should be None
        self.assertEqual(self.inh.child, var.child)
        self.assertIsNone(self.inh.mom)
        self.assertIsNone(self.inh.dad)

    def test_get_candidate_variants_monoallelic(self):
        """ test that get_candidate_variants() works for a monoallelic variant
        """

        inh = {
            "inh": ["Monoallelic"],
            "confirmed_status": ["confirmed dd gene"]
        }
        var = self.create_variant(position='150',
                                  cq='stop_gained',
                                  geno=['0/1', '0/0', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")

        self.assertEqual(
            self.inh.get_candidate_variants(),
            [(var, ['single_variant'], ['Monoallelic'], ['TEST'])])

        # check a variant that shouldn't pass the monoallelic route
        var = self.create_variant(position='150',
                                  cq='stop_gained',
                                  geno=['0/1', '0/1', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])

    def test_get_candidate_variants_imprinted(self):
        """ test that get_candidate_variants() works for imprinted variants
        """

        # check a variant where the imprinting route should work
        inh = {"inh": ["Imprinted"], "confirmed_status": ["confirmed dd gene"]}
        var = self.create_variant(position='150',
                                  cq='stop_gained',
                                  geno=['0/1', '0/1', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")

        self.assertEqual(self.inh.get_candidate_variants(),
                         [(var, ['single_variant'], ['Imprinted'], ['TEST'])])

        # de novos should now pass the imprinted route
        var = self.create_variant(position='150',
                                  cq='stop_gained',
                                  geno=['0/1', '0/0', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        #self.assertEqual(self.inh.get_candidate_variants(), [])
        self.assertEqual(self.inh.get_candidate_variants(),
                         [(var, ['single_variant'], ['Imprinted'], ['TEST'])])

        # check a variant that shouldn't pass the imprinted route due to there
        # not being a known gene.
        # NOTE: this behavior differs differs slightly from other inheritance
        # modes when there isn't any known gene. Since there are so few known
        # imprinting genes, it makes sense to only allow for these when we know
        # the mode is correct
        var = self.create_variant(position='150',
                                  cq='stop_gained',
                                  geno=['0/1', '0/1', '0/0'])
        self.inh = Autosomal([var], self.trio, None, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])

        # also check imprinting requires loss-of-function consequences
        var = self.create_variant(position='150',
                                  cq='missense_variant',
                                  geno=['0/1', '0/1', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])

        # check loss-of-function requirement for a paternally inherited variant
        var = self.create_variant(position='150',
                                  cq='missense_variant',
                                  geno=['0/1', '0/0', '0/1'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])

        # check imprinting for a biallelic variant
        var = self.create_variant(position='150',
                                  cq='stop_gained',
                                  geno=['1/1', '0/1', '0/1'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(),
                         [(var, ['single_variant'], ['Imprinted'], ['TEST'])])

        # check imprinting for a biallelic variant
        var = self.create_variant(position='150',
                                  cq='missense_variant',
                                  geno=['1/1', '0/1', '0/1'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])

    def test_get_candidate_variants_compound_het(self):
        """ test that get_candidate_variants() works for biallelic variants
        """

        inh = {"inh": ["Biallelic"], "confirmed_status": ["confirmed dd gene"]}
        var1 = self.create_variant(position='150',
                                   cq='stop_gained',
                                   geno=['0/1', '0/1', '0/0'])
        var2 = self.create_variant(position='151',
                                   cq='stop_gained',
                                   geno=['0/1', '0/0', '1/0'])
        self.inh = Autosomal([var1, var2], self.trio, inh, "TEST")

        self.assertEqual(
            sorted(self.inh.get_candidate_variants()),
            sorted([(var1, ['compound_het'], ['Biallelic'], ['TEST']),
                    (var2, ['compound_het'], ['Biallelic'], ['TEST'])]))

        # check that a single variant isn't included in the compound hets
        self.inh = Autosomal([var1], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])

    def test_check_if_any_variant_is_cnv(self):
        """ test if check_if_any_variant_is_cnv() works correctly
        """

        # generate a test variant
        chrom = "1"
        position = "60000"
        child = create_cnv("F", "unknown", chrom=chrom, pos=position)
        mom = create_cnv("F", "unknown", chrom=chrom, pos=position)
        dad = create_cnv("M", "unknown", chrom=chrom, pos=position)

        cnv_var = TrioGenotypes(chrom, position, child, mom, dad)

        # check that all variants=SNV returns False
        self.assertFalse(self.inh.check_if_any_variant_is_cnv())

        # add a CNV to the variants, then check that we find a CNV
        self.inh.variants.append(cnv_var)
        self.assertTrue(self.inh.check_if_any_variant_is_cnv())

    def set_compound_het_var(self, var, geno):
        """ convenience function to set the trio genotypes for a variant
        """

        genos = {"0": "0/0", "1": "0/1", "2": "1/1"}

        # convert the geno codes to allele codes
        child = genos[geno[0]]
        mom = genos[geno[1]]
        dad = genos[geno[2]]

        # set the genotype field for each individual
        var.child.format["GT"] = child
        var.mother.format["GT"] = mom
        var.father.format["GT"] = dad

        # and set th genotype for each individual
        var.child.set_genotype()
        var.mother.set_genotype()
        var.father.set_genotype()

        # set the trio genotypes for the inheritance object
        return var

    def test_check_compound_hets(self):
        """ test that check_compound_hets() works correctly for autosomal vars
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1",
                                   position="150",
                                   sex="F",
                                   cq="stop_gained")
        var2 = self.create_variant(chrom="1",
                                   position="160",
                                   sex="F",
                                   cq="stop_gained")
        var3 = self.create_variant(chrom="1",
                                   position="170",
                                   sex="F",
                                   cq="stop_gained")

        # set the inheritance type, the compound het type ("compound_het"
        # for autosomal variants, and start autosomal inheritance)
        # known_genes = "Biallelic"
        known_gene = {
            "inh": ["Biallelic"],
            "confirmed_status": ["confirmed dd gene"]
        }
        self.inh = Autosomal([var1, var2, var3], self.trio, known_gene, "TEST")

        variants = [(), ()]

        # check the expected "110, 101" combo passes
        variants[0] = (self.set_compound_het_var(var1, "110"), )
        variants[1] = (self.set_compound_het_var(var2, "101"), )
        self.assertEqual(sorted(self.inh.check_compound_hets(variants)),
                         sorted(variants))

        # check that > 2 valid compound hets passes all variants
        variants = [(), (), ()]
        variants[0] = (self.set_compound_het_var(var1, "110"), )
        variants[1] = (self.set_compound_het_var(var2, "101"), )
        variants[2] = (self.set_compound_het_var(var3, "110"), )
        self.assertEqual(sorted(self.inh.check_compound_hets(variants)),
                         sorted(variants))

        # check that a single var fails to give compound hets
        single_var = variants[:1]
        self.assertEqual(self.inh.check_compound_hets(single_var), [])

        # check that zero length list gives no compound hets
        no_vars = []
        self.assertEqual(self.inh.check_compound_hets(no_vars), [])

    def test_is_compound_pair_identical_variants(self):
        """ check that is_compound_pair() excludes compound pairs where the
        members are identical
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1",
                                   position="150",
                                   sex="F",
                                   cq="stop_gained")
        var2 = self.create_variant(chrom="1",
                                   position="160",
                                   sex="F",
                                   cq="stop_gained")

        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")

        # don't include pairs where the first and the second variant are identical
        self.assertFalse(self.inh.is_compound_pair(var1, var1))

        # make sure it works normally
        self.assertTrue(self.inh.is_compound_pair(var1, var2))

    def test_is_compound_pair_both_missense_with_parents(self):
        """check that is_compound_pair() excludes pairs where both are missense
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1",
                                   position="150",
                                   sex="F",
                                   cq="missense_variant")
        var2 = self.create_variant(chrom="1",
                                   position="160",
                                   sex="F",
                                   cq="missense_variant")
        var3 = self.create_variant(chrom="1",
                                   position="160",
                                   sex="F",
                                   cq="inframe_deletion")
        var4 = self.create_variant(chrom="1",
                                   position="160",
                                   sex="F",
                                   cq="stop_gained")

        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")
        var3 = self.set_compound_het_var(var3, "101")
        var4 = self.set_compound_het_var(var4, "101")

        # dont exclude pairs where both members are not loss-of-function if the
        # proband has parents
        self.assertTrue(self.inh.is_compound_pair(var1, var2))
        self.assertTrue(self.inh.is_compound_pair(var1, var3))

        # make sure it works normally
        self.assertTrue(self.inh.is_compound_pair(var1, var4))

    def test_is_compound_pair_both_missense_without_parents(self):
        """check that is_compound_pair() excludes pairs where both are missense
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1",
                                   position="150",
                                   sex="F",
                                   cq="missense_variant")
        var2 = self.create_variant(chrom="1",
                                   position="160",
                                   sex="F",
                                   cq="missense_variant")
        var3 = self.create_variant(chrom="1",
                                   position="160",
                                   sex="F",
                                   cq="inframe_deletion")
        var4 = self.create_variant(chrom="1",
                                   position="160",
                                   sex="F",
                                   cq="stop_gained")

        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")
        var3 = self.set_compound_het_var(var3, "101")
        var4 = self.set_compound_het_var(var4, "101")

        # drop the parents
        self.inh.trio.father = None
        self.inh.trio.mother = None

        # exclude pairs where both members are not loss-of-function
        self.assertFalse(self.inh.is_compound_pair(var1, var2))
        self.assertFalse(self.inh.is_compound_pair(var1, var3))

        # make sure it works if one variant is loss-of-function
        self.assertTrue(self.inh.is_compound_pair(var1, var4))

    def test_is_compound_pair_unknown_gene(self):
        """check that is_compound_pair() excludes pairs for unknown genes
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1",
                                   position="150",
                                   sex="F",
                                   cq="stop_gained")
        var2 = self.create_variant(chrom="1",
                                   position="160",
                                   sex="F",
                                   cq="stop_gained")

        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")

        var1.child.info = Info('CQ=missense_variant')
        var2.child.info = Info('CQ=missense_variant')
        var1.child.info.set_genes_and_consequence('1', 100, ('G', ), [])
        var2.child.info.set_genes_and_consequence('1', 100, ('G', ), [])

        # exclude pairs where both members are not loss-of-function
        self.assertFalse(self.inh.is_compound_pair(var1, var2))

    def test_is_compound_pair_cnv_paternal(self):
        """ check that is_compound_pair() includes pairs with CNVs
        """

        # generate a test variant
        chrom = "1"
        position = "60000"
        extra = [('CIFER_INHERITANCE', 'paternal')]
        child = create_cnv("F",
                           "paternal",
                           chrom=chrom,
                           pos=position,
                           format=extra)
        mom = create_cnv("F", "unknown", chrom=chrom, pos=position)
        dad = create_cnv("M", "unknown", chrom=chrom, pos=position)

        cnv = TrioGenotypes(chrom, position, child, mom, dad)

        # set some variants, so we can alter them later
        snv = self.create_variant(chrom="1",
                                  position="150",
                                  sex="F",
                                  cq="stop_gained")
        snv = self.set_compound_het_var(snv, "110")
        snv.child.format.pop("PP_DNM")  #make sure SNV not a DNM

        # check that these variants are compound hets, no matter which order
        # they are given as.
        self.assertTrue(self.inh.is_compound_pair(cnv, snv))
        self.assertTrue(self.inh.is_compound_pair(snv, cnv))

        #check that it works with a paternal cnv and a de novo snv
        snv = self.set_compound_het_var(snv, "100")
        snv.child.format["PP_DNM"] = '1'
        self.assertTrue(self.inh.is_compound_pair(cnv, snv))

        # check that if the SNV is inherited from the same parent as the CNV,
        # then the pair isn't a compound het.
        snv.child.format.pop("PP_DNM")
        snv = self.set_compound_het_var(snv, "101")
        self.assertFalse(self.inh.is_compound_pair(cnv, snv))

    def test_is_compound_pair_cnv_maternal(self):
        """ check that is_compound_pair() includes pairs with CNVs
        """

        # generate a test variant
        chrom = "1"
        position = "60000"
        extra = [('CIFER_INHERITANCE', 'maternal')]
        child = create_cnv("F",
                           "maternal",
                           chrom=chrom,
                           pos=position,
                           format=extra)
        mom = create_cnv("F", "unknown", chrom=chrom, pos=position)
        dad = create_cnv("M", "unknown", chrom=chrom, pos=position)

        cnv = TrioGenotypes(chrom, position, child, mom, dad)

        # set some variants, so we can alter them later
        snv = self.create_variant(chrom="1",
                                  position="150",
                                  sex="F",
                                  cq="stop_gained")
        snv = self.set_compound_het_var(snv, "101")
        snv.child.format.pop("PP_DNM")  #make sure SNV not a DNM

        # check that these variants are compound hets, no matter which order
        # they are given as.
        self.assertTrue(self.inh.is_compound_pair(cnv, snv))
        self.assertTrue(self.inh.is_compound_pair(snv, cnv))

        #check that it works with a paternal cnv and a de novo snv
        snv = self.set_compound_het_var(snv, "100")
        snv.child.format["PP_DNM"] = '1'
        self.assertTrue(self.inh.is_compound_pair(cnv, snv))

        # check that if the SNV is inherited from the same parent as the CNV,
        # then the pair isn't a compound het.
        snv = self.set_compound_het_var(snv, "110")
        snv.child.format.pop("PP_DNM")
        self.assertFalse(self.inh.is_compound_pair(cnv, snv))

    def test_is_compound_pair_cnv_de_novo(self):
        """ check that is_compound_pair() includes pairs with CNVs
        """
        chrom = "1"
        position = "60000"
        extra = [('CIFER_INHERITANCE', 'not_inherited')]
        child = create_cnv("F",
                           "maternal",
                           chrom=chrom,
                           pos=position,
                           format=extra)
        mom = create_cnv("F", "unknown", chrom=chrom, pos=position)
        dad = create_cnv("M", "unknown", chrom=chrom, pos=position)

        cnv = TrioGenotypes(chrom, position, child, mom, dad)

        # set some variants, so we can alter them later
        snv = self.create_variant(chrom="1",
                                  position="150",
                                  sex="F",
                                  cq="stop_gained")
        snv = self.set_compound_het_var(snv, "101")
        snv.child.format.pop("PP_DNM")

        # check that these variants are compound hets, no matter which order
        # they are given as.
        self.assertTrue(self.inh.is_compound_pair(cnv, snv))
        self.assertTrue(self.inh.is_compound_pair(snv, cnv))

        #check the snv can also be maternal
        snv = self.set_compound_het_var(snv, "110")
        snv.child.format.pop("PP_DNM")
        self.assertTrue(self.inh.is_compound_pair(snv, cnv))

    def test_is_compound_pair_proband_only(self):
        """ check that is_compound_pair() includes proband-only pairs
        """

        fam = Family("test")
        fam.add_child("child", 'dad_id', 'mom_id', 'F', '2', "child_vcf")
        fam.set_child()

        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1",
                                   position="150",
                                   sex="F",
                                   cq="stop_gained")
        var2 = self.create_variant(chrom="1",
                                   position="160",
                                   sex="F",
                                   cq="stop_gained")

        inh = Autosomal([var1, var2], fam, self.known_gene, "TEST")

        # check that a proband-only passes, regardless of the parental genotypes
        self.assertTrue(inh.is_compound_pair(var1, var2))

    def test_is_compound_pair_allosomal(self):
        """ check that is_compound_pair() works when the father is affected
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="X",
                                   position="150",
                                   sex="F",
                                   cq="stop_gained")
        var2 = self.create_variant(chrom="X",
                                   position="160",
                                   sex="F",
                                   cq="stop_gained")

        var1 = self.set_compound_het_var(var1, "210")
        var2 = self.set_compound_het_var(var2, "202")

        # check when the father is unaffected
        self.assertFalse(self.inh.is_compound_pair(var1, var2))

        # now check when the father is affected
        self.inh.father_affected = True
        self.assertTrue(self.inh.is_compound_pair(var1, var2))
        del var2.father.format['PP_DNM']
        # make sure we can't set the father as het on the X chrom
        with self.assertRaises(ValueError):
            self.set_compound_het_var(var2, "201")

    def test_is_compound_pair_genotype_combinations(self):
        """ check the various genotype combinations for a compound het
        """

        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1",
                                   position="150",
                                   sex="M",
                                   cq="stop_gained")
        var2 = self.create_variant(chrom="1",
                                   position="160",
                                   sex="M",
                                   cq="stop_gained")

        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")

        # check that the expected scenario passes
        self.assertTrue(self.inh.is_compound_pair(var1, var2))

        # check that compound hets with one de novo passes
        var1.child.format["PP_DNM"] = '1'
        var2.child.format.pop("PP_DNM")
        var1 = self.set_compound_het_var(var1, "100")
        var2 = self.set_compound_het_var(var2, "101")
        self.assertTrue(self.inh.is_compound_pair(var1, var2))

        var1.child.format["PP_DNM"] = '1'
        var2.child.format.pop("PP_DNM")
        var1 = self.set_compound_het_var(var1, "100")
        var2 = self.set_compound_het_var(var2, "110")
        self.assertTrue(self.inh.is_compound_pair(var1, var2))

        # check compound het with two de novos fails
        var1.child.format["PP_DNM"] = '1'
        var2.child.format["PP_DNM"] = '1'
        var1 = self.set_compound_het_var(var1, "100")
        var2 = self.set_compound_het_var(var2, "100")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))

        # check that compound hets have to be transmitted from both parents
        var1.child.format.pop("PP_DNM")  #make sure SNVs are not  DNMs
        var2.child.format.pop("PP_DNM")
        var1 = self.set_compound_het_var(var1, "101")
        var2 = self.set_compound_het_var(var2, "101")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))

        # check that compound hets have to be transmitted from both parents
        var1.child.format.pop("PP_DNM")  #make sure SNVs are not  DNMs
        var2.child.format.pop("PP_DNM")
        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "110")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))

        # make sure that only compound hets in trans pass. We exclude
        var1 = self.set_compound_het_var(var1, "111")
        var2 = self.set_compound_het_var(var2, "101")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))

        var1 = self.set_compound_het_var(var1, "111")
        var2 = self.set_compound_het_var(var2, "111")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))
Esempio n. 27
0
    def test_get_candidate_variants_imprinted(self):
        """ test that get_candidate_variants() works for imprinted variants
        """

        # check a variant where the imprinting route should work
        inh = {"inh": ["Imprinted"], "confirmed_status": ["confirmed dd gene"]}
        var = self.create_variant(position='150',
                                  cq='stop_gained',
                                  geno=['0/1', '0/1', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")

        self.assertEqual(self.inh.get_candidate_variants(),
                         [(var, ['single_variant'], ['Imprinted'], ['TEST'])])

        # de novos should now pass the imprinted route
        var = self.create_variant(position='150',
                                  cq='stop_gained',
                                  geno=['0/1', '0/0', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        #self.assertEqual(self.inh.get_candidate_variants(), [])
        self.assertEqual(self.inh.get_candidate_variants(),
                         [(var, ['single_variant'], ['Imprinted'], ['TEST'])])

        # check a variant that shouldn't pass the imprinted route due to there
        # not being a known gene.
        # NOTE: this behavior differs differs slightly from other inheritance
        # modes when there isn't any known gene. Since there are so few known
        # imprinting genes, it makes sense to only allow for these when we know
        # the mode is correct
        var = self.create_variant(position='150',
                                  cq='stop_gained',
                                  geno=['0/1', '0/1', '0/0'])
        self.inh = Autosomal([var], self.trio, None, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])

        # also check imprinting requires loss-of-function consequences
        var = self.create_variant(position='150',
                                  cq='missense_variant',
                                  geno=['0/1', '0/1', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])

        # check loss-of-function requirement for a paternally inherited variant
        var = self.create_variant(position='150',
                                  cq='missense_variant',
                                  geno=['0/1', '0/0', '0/1'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])

        # check imprinting for a biallelic variant
        var = self.create_variant(position='150',
                                  cq='stop_gained',
                                  geno=['1/1', '0/1', '0/1'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(),
                         [(var, ['single_variant'], ['Imprinted'], ['TEST'])])

        # check imprinting for a biallelic variant
        var = self.create_variant(position='150',
                                  cq='missense_variant',
                                  geno=['1/1', '0/1', '0/1'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])
class TestInheritancePy(unittest.TestCase):
    """ test the Inheritance class
    """
    
    def setUp(self):
        """ define a family and variant, and start the Inheritance class
        """
        
        # generate a test family
        sex = "F"
        mom_aff = "1"
        dad_aff = "1"
        
        self.trio = self.create_family(sex, mom_aff, dad_aff)
        
        # generate list of variants
        self.variants = [self.create_variant(sex)]
        self.variants.append(self.create_variant(sex))
        
        # make sure we've got known genes data
        self.known_gene = {"inh": ["Monoallelic"], "confirmed_status": ["confirmed dd gene"]}
        
        self.inh = Autosomal(self.variants, self.trio, self.known_gene, "1001")
    
    def create_variant(self, chrom="1", position="150", sex='F', cq=None,
            geno=['0/1', '0/0', '0/0']):
        """ creates a TrioGenotypes variant
        """
        
        # generate a test variant
        child = create_snv(sex, geno[0], cq, chrom=chrom, pos=position)
        mom = create_snv("F", geno[1], cq, chrom=chrom, pos=position)
        dad = create_snv("M", geno[2], cq, chrom=chrom, pos=position)
        
        return TrioGenotypes(chrom, position, child, mom, dad)
    
    def create_family(self, child_gender, mom_aff, dad_aff):
        """ create a default family, with optional gender and parental statuses
        """
        
        fam = Family('test')
        fam.add_child('child', 'mother', 'father', child_gender, '2', 'child_vcf')
        fam.add_mother('mother', '0', '0', 'female', mom_aff, 'mother_vcf')
        fam.add_father('father', '0', '0', 'male', dad_aff, 'father_vcf')
        fam.set_child()
        
        return fam
    
    def test_check_inheritance_mode_matches_gene_mode(self):
        """ test that check_inheritance_mode_matches_gene_mode() works correctly
        """
        
        # check that the default inheritance types have been set up correctly
        self.assertEqual(self.inh.inheritance_modes, {"Monoallelic",
            "Biallelic", "Both", 'Imprinted', 'Mosaic'})
        
        # make sure that the default var and gene inheritance work
        self.assertTrue(self.inh.check_inheritance_mode_matches_gene_mode())
        
        # check that no gene inheritance overlap fails
        self.inh.gene_inheritance = {"Mosaic"}
        self.inh.inheritance_modes = {"Monoallelic", "Biallelic", "Both", 'Imprinted'}
        self.assertFalse(self.inh.check_inheritance_mode_matches_gene_mode())
        
        # check that a single inheritance type still works
        self.inh.gene_inheritance = {"Monoallelic"}
        self.assertTrue(self.inh.check_inheritance_mode_matches_gene_mode())
        
        # check that multiple inheritance types for a gene still work
        self.inh.gene_inheritance = {"Monoallelic", "Biallelic"}
        self.assertTrue(self.inh.check_inheritance_mode_matches_gene_mode())
        
        # check that extra inheritance modes are included still work
        self.inh.gene_inheritance = {"Monoallelic", "Biallelic", "Mosaic"}
        self.assertTrue(self.inh.check_inheritance_mode_matches_gene_mode())
    
    def test_set_trio_genotypes(self):
        """ test that set_trio_genotypes() works correctly
        """
        
        # set the genotypes using the default variant
        var = self.variants[0]
        self.inh.set_trio_genotypes(var)
        
        # the genotypes for the inh object should match the vars genotypes
        self.assertEqual(self.inh.child, var.child)
        self.assertEqual(self.inh.mom, var.mother)
        self.assertEqual(self.inh.dad, var.father)
        
        # now remove the parents before re-setting the genotypes
        del var.mother
        del var.father
        self.inh.trio.father = None
        self.inh.trio.mother = None
        self.inh.set_trio_genotypes(var)
        
        # the child should match the vars genotypes, but the parent's
        # genotypes should be None
        self.assertEqual(self.inh.child, var.child)
        self.assertIsNone(self.inh.mom)
        self.assertIsNone(self.inh.dad)
    
    def test_get_candidate_variants_monoallelic(self):
        """ test that get_candidate_variants() works for a monoallelic variant
        """
        
        inh = {"inh": ["Monoallelic"], "confirmed_status": ["confirmed dd gene"]}
        var = self.create_variant(position='150', cq='stop_gained',
            geno=['0/1', '0/0', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        
        self.assertEqual(self.inh.get_candidate_variants(),
            [(var, ['single_variant'], ['Monoallelic'], ['TEST'])])
        
        # check a variant that shouldn't pass the monoallelic route
        var = self.create_variant(position='150', cq='stop_gained',
            geno=['0/1', '0/1', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])
    
    
    def test_get_candidate_variants_imprinted(self):
        """ test that get_candidate_variants() works for imprinted variants
        """
        
        # check a variant where the imprinting route should work
        inh = {"inh": ["Imprinted"], "confirmed_status": ["confirmed dd gene"]}
        var = self.create_variant(position='150', cq='stop_gained',
            geno=['0/1', '0/1', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        
        self.assertEqual(self.inh.get_candidate_variants(),
            [(var, ['single_variant'], ['Imprinted'], ['TEST'])])
        
        # de novos should now pass the imprinted route
        var = self.create_variant(position='150', cq='stop_gained',
            geno=['0/1', '0/0', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        #self.assertEqual(self.inh.get_candidate_variants(), [])
        self.assertEqual(self.inh.get_candidate_variants(),
            [(var, ['single_variant'], ['Imprinted'], ['TEST'])])
        
        # check a variant that shouldn't pass the imprinted route due to there
        # not being a known gene.
        # NOTE: this behavior differs differs slightly from other inheritance
        # modes when there isn't any known gene. Since there are so few known
        # imprinting genes, it makes sense to only allow for these when we know
        # the mode is correct
        var = self.create_variant(position='150', cq='stop_gained',
            geno=['0/1', '0/1', '0/0'])
        self.inh = Autosomal([var], self.trio, None, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])
        
        # also check imprinting requires loss-of-function consequences
        var = self.create_variant(position='150', cq='missense_variant',
            geno=['0/1', '0/1', '0/0'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])
        
        # check loss-of-function requirement for a paternally inherited variant
        var = self.create_variant(position='150', cq='missense_variant',
            geno=['0/1', '0/0', '0/1'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])
        
        # check imprinting for a biallelic variant
        var = self.create_variant(position='150', cq='stop_gained',
            geno=['1/1', '0/1', '0/1'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(),
            [(var, ['single_variant'], ['Imprinted'], ['TEST'])])
        
        # check imprinting for a biallelic variant
        var = self.create_variant(position='150', cq='missense_variant',
            geno=['1/1', '0/1', '0/1'])
        self.inh = Autosomal([var], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])
    
    def test_get_candidate_variants_compound_het(self):
        """ test that get_candidate_variants() works for biallelic variants
        """
        
        inh = {"inh": ["Biallelic"], "confirmed_status": ["confirmed dd gene"]}
        var1 = self.create_variant(position='150', cq='stop_gained',
            geno=['0/1', '0/1', '0/0'])
        var2 = self.create_variant(position='151', cq='stop_gained',
            geno=['0/1', '0/0', '1/0'])
        self.inh = Autosomal([var1, var2], self.trio, inh, "TEST")
        
        self.assertEqual(sorted(self.inh.get_candidate_variants()),
            sorted([(var1, ['compound_het'], ['Biallelic'], ['TEST']),
            (var2, ['compound_het'], ['Biallelic'], ['TEST'])]))
        
        # check that a single variant isn't included in the compound hets
        self.inh = Autosomal([var1], self.trio, inh, "TEST")
        self.assertEqual(self.inh.get_candidate_variants(), [])
    
    def test_check_if_any_variant_is_cnv(self):
        """ test if check_if_any_variant_is_cnv() works correctly
        """
        
        # generate a test variant
        chrom = "1"
        position = "60000"
        child = create_cnv("F", "unknown", chrom=chrom, pos=position)
        mom = create_cnv("F", "unknown", chrom=chrom, pos=position)
        dad = create_cnv("M", "unknown", chrom=chrom, pos=position)
        
        cnv_var = TrioGenotypes(chrom, position, child, mom, dad)
        
        # check that all variants=SNV returns False
        self.assertFalse(self.inh.check_if_any_variant_is_cnv())
        
        # add a CNV to the variants, then check that we find a CNV
        self.inh.variants.append(cnv_var)
        self.assertTrue(self.inh.check_if_any_variant_is_cnv())
    
    def set_compound_het_var(self, var, geno):
        """ convenience function to set the trio genotypes for a variant
        """
        
        genos = {"0": "0/0", "1": "0/1", "2": "1/1"}
        
        # convert the geno codes to allele codes
        child = genos[geno[0]]
        mom = genos[geno[1]]
        dad = genos[geno[2]]
        
        # set the genotype field for each individual
        var.child.format["GT"] = child
        var.mother.format["GT"] = mom
        var.father.format["GT"] = dad
        
        # and set th genotype for each individual
        var.child.set_genotype()
        var.mother.set_genotype()
        var.father.set_genotype()
        
        # set the trio genotypes for the inheritance object
        return var
    
    def test_check_compound_hets(self):
        """ test that check_compound_hets() works correctly for autosomal vars
        """
        
        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1", position="150", sex="F", cq="stop_gained")
        var2 = self.create_variant(chrom="1", position="160", sex="F", cq="stop_gained")
        var3 = self.create_variant(chrom="1", position="170", sex="F", cq="stop_gained")
        
        # set the inheritance type, the compound het type ("compound_het"
        # for autosomal variants, and start autosomal inheritance)
        # known_genes = "Biallelic"
        known_gene = {"inh": ["Biallelic"], "confirmed_status": ["confirmed dd gene"]}
        self.inh = Autosomal([var1, var2, var3], self.trio, known_gene, "TEST")
        
        variants = [(), ()]
        
        # check the expected "110, 101" combo passes
        variants[0] = (self.set_compound_het_var(var1, "110"),)
        variants[1] = (self.set_compound_het_var(var2, "101"),)
        self.assertEqual(sorted(self.inh.check_compound_hets(variants)), sorted(variants))
        
        # check that > 2 valid compound hets passes all variants
        variants = [(), (), ()]
        variants[0] = (self.set_compound_het_var(var1, "110"),)
        variants[1] = (self.set_compound_het_var(var2, "101"),)
        variants[2] = (self.set_compound_het_var(var3, "110"),)
        self.assertEqual(sorted(self.inh.check_compound_hets(variants)), sorted(variants))
        
        # check that a single var fails to give compound hets
        single_var = variants[:1]
        self.assertEqual(self.inh.check_compound_hets(single_var), [])
        
        # check that zero length list gives no compound hets
        no_vars = []
        self.assertEqual(self.inh.check_compound_hets(no_vars), [])
    
    def test_is_compound_pair_identical_variants(self):
        """ check that is_compound_pair() excludes compound pairs where the
        members are identical
        """
        
        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1", position="150", sex="F", cq="stop_gained")
        var2 = self.create_variant(chrom="1", position="160", sex="F", cq="stop_gained")
        
        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")
        
        # don't include pairs where the first and the second variant are identical
        self.assertFalse(self.inh.is_compound_pair(var1, var1))
        
        # make sure it works normally
        self.assertTrue(self.inh.is_compound_pair(var1, var2))
    
    def test_is_compound_pair_both_missense_with_parents(self):
        """check that is_compound_pair() excludes pairs where both are missense
        """
        
        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1", position="150", sex="F", cq="missense_variant")
        var2 = self.create_variant(chrom="1", position="160", sex="F", cq="missense_variant")
        var3 = self.create_variant(chrom="1", position="160", sex="F", cq="inframe_deletion")
        var4 = self.create_variant(chrom="1", position="160", sex="F", cq="stop_gained")
        
        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")
        var3 = self.set_compound_het_var(var3, "101")
        var4 = self.set_compound_het_var(var4, "101")
        
        # dont exclude pairs where both members are not loss-of-function if the
        # proband has parents
        self.assertTrue(self.inh.is_compound_pair(var1, var2))
        self.assertTrue(self.inh.is_compound_pair(var1, var3))
        
        # make sure it works normally
        self.assertTrue(self.inh.is_compound_pair(var1, var4))
    
    def test_is_compound_pair_both_missense_without_parents(self):
        """check that is_compound_pair() excludes pairs where both are missense
        """
        
        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1", position="150", sex="F", cq="missense_variant")
        var2 = self.create_variant(chrom="1", position="160", sex="F", cq="missense_variant")
        var3 = self.create_variant(chrom="1", position="160", sex="F", cq="inframe_deletion")
        var4 = self.create_variant(chrom="1", position="160", sex="F", cq="stop_gained")
        
        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")
        var3 = self.set_compound_het_var(var3, "101")
        var4 = self.set_compound_het_var(var4, "101")
        
        # drop the parents
        self.inh.trio.father = None
        self.inh.trio.mother = None
        
        # exclude pairs where both members are not loss-of-function
        self.assertFalse(self.inh.is_compound_pair(var1, var2))
        self.assertFalse(self.inh.is_compound_pair(var1, var3))
        
        # make sure it works if one variant is loss-of-function
        self.assertTrue(self.inh.is_compound_pair(var1, var4))
    
    def test_is_compound_pair_unknown_gene(self):
        """check that is_compound_pair() excludes pairs for unknown genes
        """
        
        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1", position="150", sex="F", cq="stop_gained")
        var2 = self.create_variant(chrom="1", position="160", sex="F", cq="stop_gained")
        
        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")
        
        var1.child.info = Info('CQ=missense_variant')
        var2.child.info = Info('CQ=missense_variant')
        var1.child.info.set_genes_and_consequence('1', 100, ('G', ), [])
        var2.child.info.set_genes_and_consequence('1', 100, ('G', ), [])
        
        # exclude pairs where both members are not loss-of-function
        self.assertFalse(self.inh.is_compound_pair(var1, var2))
    
    def test_is_compound_pair_cnv_paternal(self):
        """ check that is_compound_pair() includes pairs with CNVs
        """
        
        # generate a test variant
        chrom = "1"
        position = "60000"
        extra = [('CIFER_INHERITANCE', 'paternal')]
        child = create_cnv("F", "paternal", chrom=chrom, pos=position, format=extra)
        mom = create_cnv("F", "unknown", chrom=chrom, pos=position)
        dad = create_cnv("M", "unknown", chrom=chrom, pos=position)
        
        cnv = TrioGenotypes(chrom, position, child, mom, dad)
        
        # set some variants, so we can alter them later
        snv = self.create_variant(chrom="1", position="150", sex="F", cq="stop_gained")
        snv = self.set_compound_het_var(snv, "110")
        
        # check that these variants are compound hets, no matter which order
        # they are given as.
        self.assertTrue(self.inh.is_compound_pair(cnv, snv))
        self.assertTrue(self.inh.is_compound_pair(snv, cnv))
        
        # check that if the SNV is inherited from the same parent as the CNV,
        # then the pair isn't a compound het.
        snv = self.set_compound_het_var(snv, "101")
        self.assertFalse(self.inh.is_compound_pair(cnv, snv))
    
    def test_is_compound_pair_cnv_maternal(self):
        """ check that is_compound_pair() includes pairs with CNVs
        """
        
        # generate a test variant
        chrom = "1"
        position = "60000"
        extra = [('CIFER_INHERITANCE', 'maternal')]
        child = create_cnv("F", "maternal", chrom=chrom, pos=position, format=extra)
        mom = create_cnv("F", "unknown", chrom=chrom, pos=position)
        dad = create_cnv("M", "unknown", chrom=chrom, pos=position)
        
        cnv = TrioGenotypes(chrom, position, child, mom, dad)
        
        # set some variants, so we can alter them later
        snv = self.create_variant(chrom="1", position="150", sex="F", cq="stop_gained")
        snv = self.set_compound_het_var(snv, "101")
        
        # check that these variants are compound hets, no matter which order
        # they are given as.
        self.assertTrue(self.inh.is_compound_pair(cnv, snv))
        
        # check that if the SNV is inherited from the same parent as the CNV,
        # then the pair isn't a compound het.
        snv = self.set_compound_het_var(snv, "110")
        self.assertFalse(self.inh.is_compound_pair(cnv, snv))
    
    def test_is_compound_pair_proband_only(self):
        """ check that is_compound_pair() includes proband-only pairs
        """
        
        fam = Family("test")
        fam.add_child("child", 'dad_id', 'mom_id', 'F', '2',  "child_vcf")
        fam.set_child()
        
        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1", position="150", sex="F", cq="stop_gained")
        var2 = self.create_variant(chrom="1", position="160", sex="F", cq="stop_gained")
        
        inh = Autosomal([var1, var2], fam, self.known_gene, "TEST")
        
        # check that a proband-only passes, regardless of the parental genotypes
        self.assertTrue(inh.is_compound_pair(var1, var2))
    
    def test_is_compound_pair_allosomal(self):
        """ check that is_compound_pair() works when the father is affected
        """
        
        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="X", position="150", sex="F", cq="stop_gained")
        var2 = self.create_variant(chrom="X", position="160", sex="F", cq="stop_gained")
        
        var1 = self.set_compound_het_var(var1, "210")
        var2 = self.set_compound_het_var(var2, "202")
        
        # check when the father is unaffected
        self.assertFalse(self.inh.is_compound_pair(var1, var2))
        
        # now check when the father is affected
        self.inh.father_affected = True
        self.assertTrue(self.inh.is_compound_pair(var1, var2))
        del var2.father.format['PP_DNM']
        # make sure we can't set the father as het on the X chrom
        with self.assertRaises(ValueError):
            self.set_compound_het_var(var2, "201")
    
    def test_is_compound_pair_genotype_combinations(self):
        """ check the various genotype combinations for a compound het
        """
        
        # set some variants, so we can alter them later
        var1 = self.create_variant(chrom="1", position="150", sex="M", cq="stop_gained")
        var2 = self.create_variant(chrom="1", position="160", sex="M", cq="stop_gained")
        
        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "101")
        
        # check that the expected scenario passes
        self.assertTrue(self.inh.is_compound_pair(var1, var2))
        
        # check that compound hets with de novos fail
        var1 = self.set_compound_het_var(var1, "100")
        var2 = self.set_compound_het_var(var2, "101")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))
        
        # check that compound hets have to be transmitted from both parents
        var1 = self.set_compound_het_var(var1, "101")
        var2 = self.set_compound_het_var(var2, "101")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))
        
        # check that compound hets have to be transmitted from both parents
        var1 = self.set_compound_het_var(var1, "110")
        var2 = self.set_compound_het_var(var2, "110")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))
        
        # make sure that only compound hets in trans pass. We exclude
        var1 = self.set_compound_het_var(var1, "111")
        var2 = self.set_compound_het_var(var2, "101")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))
        
        var1 = self.set_compound_het_var(var1, "111")
        var2 = self.set_compound_het_var(var2, "111")
        self.assertFalse(self.inh.is_compound_pair(var1, var2))
class TestAutosomalPy(unittest.TestCase):
    """ test the Autosomal class
    """
    
    def setUp(self):
        """ define a family and variant, and start the Autosomal class
        """
        
        # generate a test family
        child_gender = "F"
        mom_aff = "1"
        dad_aff = "1"
        
        self.trio = self.create_family(child_gender, mom_aff, dad_aff)
        
        # generate a test variant
        child_var = self.create_snv(child_gender, "0/1")
        mom_var = self.create_snv("F", "0/0")
        dad_var = self.create_snv("M", "0/0")
        
        var = TrioGenotypes(child_var)
        var.add_mother_variant(mom_var)
        var.add_father_variant(dad_var)
        self.variants = [var]
        
        # make sure we've got known genes data
        self.known_genes = {"TEST": {"inh": ["Monoallelic"], "confirmed_status": ["Confirmed DD Gene"]}}
        
        self.inh = Autosomal(self.variants, self.trio, self.known_genes, "TEST")
        self.inh.is_lof = var.child.is_lof()
    
    def create_snv(self, gender, genotype):
        """ create a default variant
        """
        
        chrom = "1"
        pos = "15000000"
        snp_id = "."
        ref = "A"
        alt = "G"
        filt = "PASS"
        
        # set up a SNV object, since SNV inherits VcfInfo
        var = SNV(chrom, pos, snp_id, ref, alt, filt)
        
        info = "HGNC=TEST;CQ=missense_variant;random_tag"
        format_keys = "GT:DP"
        sample_values = genotype + ":50"
        
        var.add_info(info)
        var.add_format(format_keys, sample_values)
        var.set_gender(gender)
        var.set_genotype()
        
        return var
        
    def create_cnv(self, gender, inh, chrom, pos):
        """ create a default variant
        """
        
        snp_id = "."
        ref = "A"
        alt = "<DUP>"
        filt = "PASS"
        
        # set up a SNV object, since SNV inherits VcfInfo
        var = CNV(chrom, pos, snp_id, ref, alt, filt)
        
        info = "HGNC=TEST;HGNC_ALL=TEST;END=16000000;SVLEN=5000"
        format_keys = "INHERITANCE:DP"
        sample_values = inh + ":50"
        
        var.add_info(info)
        var.add_format(format_keys, sample_values)
        var.set_gender(gender)
        var.set_genotype()
        
        return var
    
    def create_family(self, child_gender, mom_aff, dad_aff):
        """ create a default family, with optional gender and parental statuses
        """
        
        fam = Family("test")
        fam.add_child("child", "child_vcf", "2", child_gender)
        fam.add_mother("mother", "mother_vcf", mom_aff, "2")
        fam.add_father("father", "father_vcf", dad_aff, "1")
        fam.set_child()
        
        return fam
    
    def set_trio_genos(self, var, geno):
        """ convenience function to set the trio genotypes for a variant
        """
        
        genos = {"0": "0/0", "1": "0/1", "2": "1/1"}
        
        # convert the geno codes to allele codes
        child = genos[geno[0]]
        mom = genos[geno[1]]
        dad = genos[geno[2]]
        
        # set the genotype field for each individual
        var.child.format["GT"] = child
        var.mother.format["GT"] = mom
        var.father.format["GT"] = dad
        
        # and set th genotype for each individual
        var.child.set_genotype()
        var.mother.set_genotype()
        var.father.set_genotype()
        
        # set the trio genotypes for the inheritance object
        self.inh.set_trio_genotypes(var)
    
    def test_check_variant_without_parents(self):
        """ test that check_variant_without_parents() works correctly
        """
        
        var = self.variants[0]
        self.set_trio_genos(var, "100")
        
        # remove the parents, so it appears the var lacks parental information
        self.inh.trio.mother = None
        self.inh.trio.father = None
        
        # check for monoallelic inheritance
        self.assertEqual(self.inh.check_variant_without_parents("Monoallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "autosomal without parents")
        
        # check for biallelic inheritance
        self.assertEqual(self.inh.check_variant_without_parents("Biallelic"), "compound_het")
        
        self.set_trio_genos(var, "200")
        self.assertEqual(self.inh.check_variant_without_parents("Monoallelic"), "nothing")
        self.assertEqual(self.inh.check_variant_without_parents("Biallelic"), "single_variant")
    
    def test_check_heterozygous_de_novo(self):
        """ test that check_heterozygous() works correctly for de novos
        """
        
        var = self.variants[0]
        self.inh.set_trio_genotypes(var)
        # check for monoallelic inheritance
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "de novo as single_variant")
        
        # check for biallelic inheritance
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "de novo as compound_het")
        
        
        for geno in ["101", "102", "110", "112", "122"]:
            self.set_trio_genos(var, geno)
            self.inh.check_heterozygous("Monoallelic")
            self.assertNotEqual(self.inh.log_string, "de novo as single_variant")
        
    def test_check_heterozygous_affected_mother(self):
        """ test that check_heterozygous() works correctly for affected mothers
        """
        
        var = self.variants[0]
        
        # check that trio = 110, with het affected mother is captured
        self.set_trio_genos(var, "110")
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "transmitted from aff, other parent non-carrier or aff")
        
        # check that when the other parent is also non-ref, the variant is no
        # longer captured, unless the parent is affected
        self.set_trio_genos(var, "111")
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "typically for trios with non-de novo unaffected parents")
        
        self.inh.father_affected = True
        self.inh.check_heterozygous("Monoallelic")
        self.assertEqual(self.inh.log_string, "transmitted from aff, other parent non-carrier or aff")
    
    def test_check_heterozygous_affected_father(self):
        """ test that check_heterozygous() works correctly for affected fathers
        """
        
        var = self.variants[0]
        # set the father as non-ref genotype and affected
        self.set_trio_genos(var, "101")
        self.inh.father_affected = True
        
        # check that the het proband, with het affected father is captured
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "transmitted from aff, other parent non-carrier or aff")
        
        # check that when the other parent is also non-ref, the variant is no
        # longer captured, unless the parent is affected
        self.set_trio_genos(var, "111")
        self.assertEqual(self.inh.check_heterozygous("Monoallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "typically for trios with non-de novo unaffected parents")
        
        self.inh.mother_affected = True
        self.inh.check_heterozygous("Monoallelic")
        self.assertEqual(self.inh.log_string, "transmitted from aff, other parent non-carrier or aff")
    
    def test_check_heterozygous_biallelic_non_ref_father(self):
        """ test that check_heterozygous() works correctly for biallelic genes
        """
        
        var = self.variants[0]
        # check for trio = 101
        self.set_trio_genos(var, "101")
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "het-check for recessive genes and unaff parents not homoz")
        
        # check that trio = 102, with affected father comes through other route
        self.set_trio_genos(var, "102")
        self.inh.father_affected = True
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "transmitted from aff, other parent non-carrier or aff")
        
        # check for trio = 102, without affected father
        self.inh.father_affected = False
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "typically for trios with non-de novo unaffected parents")
    
    def test_check_heterozygous_biallelic_non_ref_mother(self):
        """ test that check_heterozygous() works correctly for biallelic genes
        """
        
        # check for trio = 110
        var = self.variants[0]
        self.set_trio_genos(var, "110")
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "het-check for recessive genes and unaff parents not homoz")
        
        # check for trio = 120, with affected mother comes through other route
        var = self.variants[0]
        self.set_trio_genos(var, "120")
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "transmitted from aff, other parent non-carrier or aff")
        
        # check for trio = 120, without affected mother
        self.set_trio_genos(var, "120")
        self.inh.mother_affected = False
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "typically for trios with non-de novo unaffected parents")
    
    def test_check_heterozygous_biallelic_both_parents_non_ref(self):
        """ test that check_heterozygous() works correctly for biallelic genes
        """
        
        # check for trio = 111
        var = self.variants[0]
        self.set_trio_genos(var, "111")
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "het-check for recessive genes and unaff parents not homoz")
        
        # check for trio = 121 with affected mother, but unaffected father
        self.set_trio_genos(var, "121")
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "het-check for recessive genes and unaff parents not homoz")
        
        # check for trio = 112 with affected father, but unaffected mother
        self.set_trio_genos(var, "112")
        self.inh.mother_affected = False
        self.inh.father_affected = True
        
        self.assertEqual(self.inh.check_heterozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "het-check for recessive genes and unaff parents not homoz")
    
    def test_check_homozygous(self):
        """ test that check_homozygous() works correctly
        """
        
        var = self.variants[0]
        
        # check for trio = 200, which is non-mendelian
        self.set_trio_genos(var, "200")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")
        
        # check for 201, which is non-mendelian
        self.set_trio_genos(var, "201")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")
        
        # check for 210, which is non-mendelian
        self.set_trio_genos(var, "210")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")
        
    def test_check_homozygous_with_cnv(self):
        """ test that check_homozygous() works correctly for variant lists with CNVs
        """
        
        # generate a test variant
        chrom = "1"
        position = "60000"
        child_var = self.create_cnv("F", "unknown", chrom, position)
        mom_var = self.create_cnv("F", "unknown", chrom, position)
        dad_var = self.create_cnv("M", "unknown", chrom, position)
        
        cnv_var = TrioGenotypes(child_var)
        cnv_var.add_mother_variant(mom_var)
        cnv_var.add_father_variant(dad_var)
        
        var = self.variants[0]
        
        # check for trio = 200, which is non-mendelian
        self.set_trio_genos(var, "200")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-mendelian trio")
        
        # check when a CNV is in the variants list
        self.inh.variants.append(cnv_var)
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "compound_het")
        self.assertEqual(self.inh.log_string, "non-mendelian, but CNV might affect call")
    
    def test_check_homozygous_biallelic(self):
        """ test that check_homozygous() works correctly for biallelic genes
        """
        
        var = self.variants[0]
        
        # check for trio = 211
        self.set_trio_genos(var, "211")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "both parents het in biallelic gene")
        
        # and check for trio = 221, but unaffected mother
        self.set_trio_genos(var, "221")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")
        
        # and check for trio = 221, with affected mother
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "homoz parent aff")
        
        # and check for trio = 222, with affected mother only, should fail
        self.set_trio_genos(var, "222")
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")
        
        # and check for trio = 222, with both parents affected
        self.inh.father_affected = True
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "homoz parent aff")
        
        # and check for trio = 212, with affected father
        self.set_trio_genos(var, "212")
        self.inh.father_affected = True
        self.inh.mother_affected = False
        self.assertEqual(self.inh.check_homozygous("Biallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "homoz parent aff")
    
    def test_check_homozygous_monoallelic(self):
        """ test that check_homozygous() works correctly for monoallelic genes
        """
        
        var = self.variants[0]
        
        # check for trio = 211, without affected father
        self.set_trio_genos(var, "211")
        self.assertEqual(self.inh.check_homozygous("Monoallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")
        
        # check for trio = 211, with affected father only
        self.inh.father_affected = True
        self.assertEqual(self.inh.check_homozygous("Monoallelic"), "nothing")
        self.assertEqual(self.inh.log_string, "non-causal homozygous variant")
        
        # check for trio = 211, with both parents affected
        self.inh.mother_affected = True
        self.assertEqual(self.inh.check_homozygous("Monoallelic"), "single_variant")
        self.assertEqual(self.inh.log_string, "transmitted from affected parents")