def test_load_trio(self): ''' test that load_trio() works correctly ''' def make_vcf(person): # make a VCF, where one line would pass the default filtering vcf = make_vcf_header() vcf.append(make_vcf_line(pos=1, extra='HGNC=TEST;MAX_AF=0.0001')) vcf.append(make_vcf_line(pos=2, extra='HGNC=ATRX;MAX_AF=0.0001')) path = os.path.join(self.temp_dir, "{}.vcf.gz".format(person)) self.write_gzipped_vcf(path, vcf) return path child_path = make_vcf('child') mother_path = make_vcf('mother') father_path = make_vcf('father') family = Family('fam_id') family.add_child('sample', 'mother_id', 'father_id', 'female', '2', child_path) family.add_mother('mother_id', '0', '0', 'female', '1', mother_path) family.add_father('father_id', '0', '0', 'male', '1', father_path) family.set_child() # define the parameters and values for the SNV class args = {'chrom': "1", 'position': 2, 'id': ".", 'ref': "G", 'alts': "T", 'filter': "PASS", 'info': "CQ=missense_variant;HGNC=ATRX;MAX_AF=0.0001", 'format': "DP:GT", 'sample': "50:0/1", 'gender': "female", 'mnv_code': None} dad_args = copy.deepcopy(args) dad_args['gender'] = 'male' self.assertEqual(self.vcf_loader.load_trio(family), [TrioGenotypes(chrom="1", pos=2, child=SNV(**args), mother=SNV(**args), father=SNV(**dad_args)) ])
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 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 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 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_load_trio(self): ''' test that load_trio() works correctly ''' def make_vcf(person): # make a VCF, where one line would pass the default filtering vcf = make_vcf_header() vcf.append(make_vcf_line(pos=1, extra='HGNC=TEST;MAX_AF=0.0001')) vcf.append(make_vcf_line(pos=2, extra='HGNC=ATRX;MAX_AF=0.0001')) path = os.path.join(self.temp_dir, "{}.vcf.gz".format(person)) write_gzipped_vcf(path, vcf) return path child_path = make_vcf('child') mother_path = make_vcf('mother') father_path = make_vcf('father') family = Family('fam_id') family.add_child('sample', 'mother_id', 'father_id', 'female', '2', child_path) family.add_mother('mother_id', '0', '0', 'female', '1', mother_path) family.add_father('father_id', '0', '0', 'male', '1', father_path) family.set_child() sum_x_lr2_proband = 0 # define the parameters and values for the SNV class args = { 'chrom': "1", 'position': 2, 'id': ".", 'ref': "G", 'alts': "T", 'filter': "PASS", 'info': "CQ=missense_variant;HGNC=ATRX;MAX_AF=0.0001", 'format': "DP:GT:AD", 'sample': "50:0/1:10,10", 'gender': "female", 'mnv_code': None, 'qual': '1000' } dad_args = copy.deepcopy(args) dad_args['gender'] = 'male' self.assertEqual(load_trio(family, sum_x_lr2_proband), [ TrioGenotypes(chrom="1", pos=2, child=SNV(**args), mother=SNV(**args), father=SNV(**dad_args)) ])
def test_get_vcf_provenance(self): """ test that get_vcf_provenance() works correctly """ path = os.path.join(self.temp_dir, "temp.vcf") gz_path = os.path.join(self.temp_dir, "temp.vcf.gz") date_path = os.path.join(self.temp_dir, "temp.process.2014-02-20.vcf") family = Family('famid') family.add_child('child_id', 'mother', 'father', 'f', '2', path) family.add_mother('mom_id', '0', '0', 'female', '1', gz_path) family.add_father('dad_id', '0', '0', 'male', '1', date_path) family.set_child() vcf = make_minimal_vcf() vcf_string = "".join(vcf) if IS_PYTHON3: vcf_string = vcf_string.encode("utf-8") ungzipped_hash = hashlib.sha1(vcf_string).hexdigest() header = vcf[:4] write_temp_vcf(path, vcf) # check that the file defs return correctly (checksum, basename, date) = get_vcf_provenance(family.child) self.assertEqual(checksum, ungzipped_hash) self.assertEqual(basename, "temp.vcf") self.assertEqual(date, "2014-01-01") # now write a gzip file, and check that we get the correct hash write_gzipped_vcf(gz_path, vcf) handle = open(gz_path, "rb") gzipped_hash = hashlib.sha1(handle.read()).hexdigest() handle.close() (checksum, basename, date) = get_vcf_provenance(family.mother) self.assertEqual(checksum, gzipped_hash) # check that when a fileDate isn't available in the VCF, we can pick # the date from the path vcf.pop(1) write_temp_vcf(date_path, vcf) (checksum, basename, date) = get_vcf_provenance(family.father) self.assertEqual(date, "2014-02-20") # and check we get null values if the family member is not present family.father = None provenance = get_vcf_provenance(family.father) self.assertEqual(provenance, ('NA', 'NA', 'NA'))
def test_find_variants(self): """ test that find_variants() works correctly """ # define the trio, so that we can know whether the parents are affected. # The child also needs to be included and set, so that we can get the # child ID for logging purposes. family = Family("famID") family.add_child("child_id", 'dad_id', 'mom_id', 'f', '2', "/vcf/path") family.add_father("dad_id", '0', '0', 'm', '1', "/vcf/path") family.add_mother("mom_id", '0', '0', 'f', '1', "/vcf/path") family.set_child() # create variants that cover various scenarios snv1 = create_variant("F", "missense_variant|missense_variant", "TEST1|TEST2") snv2 = create_variant("F", "missense_variant|synonymous_variant", "OTHER1|OTHER2") snv3 = create_variant("F", "missense_variant", "") snv4 = create_variant("F", "missense_variant", "TESTX", chrom="X") self.finder.known_genes = {"TEST1": {"inh": ["Monoallelic"]}, "OTHER1": {"inh": ["Monoallelic"]}, "OTHER2": {"inh": ["Monoallelic"]}, "TESTX": {"inh": ["X-linked dominant"]}} # check the simplest case, a variant in a known gene self.assertEqual(self.finder.find_variants([snv1], "TEST1", family), [(snv1, ["single_variant"], ["Monoallelic"], ["TEST1"])]) # check that a gene not in a known gene does not pass self.assertEqual(self.finder.find_variants([snv1], "TEST2", family), []) # check a variant where the gene is known, but the consequence for that # gene is not functional, does not pass self.assertEqual(self.finder.find_variants([snv2], "OTHER2", family), []) # check that intergenic variants (which lack HGNC symbols) do not pass self.assertEqual(self.finder.find_variants([snv3], None, family), []) # check that a variant on chrX passes through the allosomal instance self.assertEqual(self.finder.find_variants([snv4], "TESTX", family), [(snv4, ["single_variant"], ["X-linked dominant"], ["TESTX"])]) # remove the known genes, so that the variants in unknown genes pass self.finder.known_genes = None self.assertEqual(sorted(self.finder.find_variants([snv1], "TEST2", family)), [(snv1, ["single_variant"], ["Monoallelic"], ["TEST2"]), (snv1, ["single_variant"], ["Mosaic"], ["TEST2"])]) # but variants without gene symbols still are excluded self.assertEqual(self.finder.find_variants([snv3], None, family), [])
def test_get_vcf_provenance(self): """ test that get_vcf_provenance() works correctly """ path = os.path.join(self.temp_dir, "temp.vcf") gz_path = os.path.join(self.temp_dir, "temp.vcf.gz") date_path = os.path.join(self.temp_dir, "temp.process.2014-02-20.vcf") family = Family('famid') family.add_child('child_id', 'mother', 'father', 'f', '2', path) family.add_mother('mom_id', '0', '0', 'female', '1', gz_path) family.add_father('dad_id', '0', '0', 'male', '1', date_path) family.set_child() vcf = make_minimal_vcf() vcf_string = "".join(vcf) if IS_PYTHON3: vcf_string = vcf_string.encode("utf-8") ungzipped_hash = hashlib.sha1(vcf_string).hexdigest() header = vcf[:4] write_temp_vcf(path, vcf) # check that the file defs return correctly (checksum, basename, date) = get_vcf_provenance(family.child) self.assertEqual(checksum, ungzipped_hash) self.assertEqual(basename, "temp.vcf") self.assertEqual(date, "2014-01-01") # now write a gzip file, and check that we get the correct hash write_gzipped_vcf(gz_path, vcf) handle = open(gz_path, "rb") gzipped_hash = hashlib.sha1(handle.read()).hexdigest() handle.close() (checksum, basename, date) = get_vcf_provenance(family.mother) self.assertEqual(checksum, gzipped_hash) # check that when a fileDate isn't available in the VCF, we can pick # the date from the path vcf.pop(1) write_temp_vcf(date_path, vcf) (checksum, basename, date) = get_vcf_provenance(family.father) self.assertEqual(date, "2014-02-20") # and check we get null values if the family member is not present family.father = None provenance = get_vcf_provenance(family.father) self.assertEqual(provenance, ('NA', 'NA', 'NA'))
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 setUp(self): """ define a default VcfInfo object """ family = Family("FamID") family.add_child("child_id", "/child/path", "2", "M") family.add_mother("mom_id", "/mother/path", "1", "F") family.add_father("dad_id", "/father/path", "2", "M") family.set_child() variants = [] snv = self.create_var("1", True) cnv = self.create_var("1", False) variants.append((snv, ["single_variant"], ["Monoallelic"], ["ATRX"])) variants.append((cnv, ["single_variant"], ["Monoallelic"], ["ATRX"])) self.post_filter = PostInheritanceFilter(variants, family)
def setUp(self): """ define a default variant object """ Info.populations = ['AFR_AF'] family = Family('test') family.add_child('child', 'mother', 'father', 'male', '2', 'child_vcf') family.add_mother('mother', '0', '0', 'female', '1', 'mother_vcf') family.add_father('father', '0', '0', 'male', '2', 'father_vcf') family.set_child() self.variants = [] snv = self.create_var("1", True) cnv = self.create_var("1", False) self.variants.append((snv, ["single_variant"], ["Monoallelic"], ["ATRX"])) self.variants.append((cnv, ["single_variant"], ["Monoallelic"], ["ATRX"])) self.post_filter = PostInheritanceFilter(family)
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 setUp(self): """ define a default variant object """ Info.populations = ['AFR_AF'] family = Family('test') family.add_child('child', 'mother', 'father', 'male', '2', 'child_vcf') family.add_mother('mother', '0', '0', 'female', '1', 'mother_vcf') family.add_father('father', '0', '0', 'male', '2', 'father_vcf') family.set_child() self.variants = [] snv = self.create_var("1", True) cnv = self.create_var("1", False) self.variants.append( (snv, ["single_variant"], ["Monoallelic"], ["ATRX"])) self.variants.append( (cnv, ["single_variant"], ["Monoallelic"], ["ATRX"])) self.post_filter = PostInheritanceFilter(family)
class TestFamily(unittest.TestCase): """ """ def setUp(self): """ define a default Person object """ ID = "fam_ID" self.family = Family(ID) def test__iter__(self): ''' test that __iter__() works correctly ''' family_id, person_id, mom_id, dad_id = 'fam_ID', 'child', 'dad', 'mom', path, status, sex = 'child.vcf', '2', 'M' child = Person(family_id, person_id, dad_id, mom_id, sex, status, path) self.family.add_child(person_id, dad_id, mom_id, sex, status, path) self.family.set_child() # check the Family iterates by getting a list of the Family object members = list(self.family) self.assertEqual(members, [child, None, None]) def test_add_father(self): """ test that add_father() works correctly """ person_id = "parent_ID" path = "/home/parent.vcf" status = "1" sex = "1" dad_id = "0" mom_id = "0" # check that adding a male father doesn't raise an error self.family.add_father(person_id, dad_id, mom_id, sex, status, path) # check that adding a father for a second time is fine, but adding # a different father raises an error self.family.add_father(person_id, dad_id, mom_id, sex, status, path) with self.assertRaises(ValueError): self.family.add_father("different_ID", dad_id, mom_id, sex, status, path) # check that adding a female father raises an error self.setUp() sex = "2" with self.assertRaises(ValueError): self.family.add_father(person_id, dad_id, mom_id, sex, status, path) def test_add_mother(self): """ test that add_mother() works correctly """ person_id = "parent_ID" path = "/home/parent.vcf" status = "1" sex = "2" dad_id = "0" mom_id = "0" # check that adding a female mother doesn't raise an error self.family.add_mother(person_id, dad_id, mom_id, sex, status, path) # check that adding a mother for a second time is fine, but adding # a different mother raises an error self.family.add_mother(person_id, dad_id, mom_id, sex, status, path) with self.assertRaises(ValueError): self.family.add_mother("different_ID", dad_id, mom_id, sex, status, path) # check that adding a male mother raises an error self.setUp() sex = "1" with self.assertRaises(ValueError): self.family.add_mother(person_id, dad_id, mom_id, sex, status, path) def test_add_child(self): """ check that add_child() works correctly """ # check that we can add one child self.family.add_child("child1", 'dad', 'mom', 'male', '2', "/home/child1.vcf") self.assertEqual(len(self.family.children), 1) # check that adding multiple children works correctly self.family.add_child("child2", 'dad', 'mom', 'female', '2', "/home/child2.vcf") self.family.add_child("child3", 'dad', 'mom', 'male', '2', "/home/child3.vcf") self.assertEqual(len(self.family.children), 3) def test_set_child(self): """ test that set_child() works correctly """ # add one child self.family.add_child("child1", 'dad', 'mom', 'male', '2', "/home/child1.vcf") # check that the child can be set correctly self.family.set_child() self.assertEqual(self.family.child, self.family.children[0]) # add more children self.family.add_child("child2", 'dad', 'mom', 'male', '2', "/home/child2.vcf") self.family.add_child("child3", 'dad', 'mom', 'female', '2', "/home/child3.vcf") # check that the child can be set correctly with multiple children self.family.set_child() self.assertIn(self.family.child, self.family.children) def test_set_child_examined(self): """ test that set_child_examined() works correctly """ # add one child self.family.add_child("child1", 'dad', 'mom', 'male', '2', "/home/child1.vcf") # check that the child can be set correctly, and can be set as having # been examined self.family.set_child() self.family.set_child_examined() self.assertTrue(self.family.children[0].is_analysed()) self.assertIsNone(self.family.child) # add another child, and check that when we set the child, we now pick # up this child since the other one has previously been examined self.family.add_child("child2", 'dad', 'mom', 'female', '2', "/home/child2.vcf") self.family.set_child() self.assertEqual(self.family.child, self.family.children[1]) # make sure that set_child_examined() doesn't default to None if we # have children left to analyse self.family.add_child("child3", 'dad', 'mom', 'female', '2', "/home/child3.vcf") self.family.set_child() self.family.set_child_examined() self.assertIsNotNone(self.family.child) # and set child = None once we have analysed all the children self.family.set_child() self.family.set_child_examined() self.assertIsNone(self.family.child)
def test_find_variants(self): """ test that find_variants() works correctly """ # define the trio, so that we can know whether the parents are affected. # The child also needs to be included and set, so that we can get the # child ID for logging purposes. family = Family("famID") family.add_child("child_id", 'dad_id', 'mom_id', 'f', '2', "/vcf/path") family.add_father("dad_id", '0', '0', 'm', '1', "/vcf/path") family.add_mother("mom_id", '0', '0', 'f', '1', "/vcf/path") family.set_child() # create variants that cover various scenarios snv1 = create_variant("F", "missense_variant|missense_variant", "TEST1|TEST2") snv2 = create_variant("F", "missense_variant|synonymous_variant", "OTHER1|OTHER2") snv3 = create_variant("F", "missense_variant", "") snv4 = create_variant("F", "missense_variant", "TESTX", chrom="X") self.finder.known_genes = { "TEST1": { "inh": ["Monoallelic"] }, "OTHER1": { "inh": ["Monoallelic"] }, "OTHER2": { "inh": ["Monoallelic"] }, "TESTX": { "inh": ["X-linked dominant"] } } # check the simplest case, a variant in a known gene self.assertEqual( self.finder.find_variants([snv1], "TEST1", family), [(snv1, ["single_variant"], ["Monoallelic"], ["TEST1"])]) # check that a gene not in a known gene does not pass self.assertEqual(self.finder.find_variants([snv1], "TEST2", family), []) # check a variant where the gene is known, but the consequence for that # gene is not functional, does not pass self.assertEqual(self.finder.find_variants([snv2], "OTHER2", family), []) # check that intergenic variants (which lack HGNC symbols) do not pass self.assertEqual(self.finder.find_variants([snv3], None, family), []) # check that a variant on chrX passes through the allosomal instance self.assertEqual( self.finder.find_variants([snv4], "TESTX", family), [(snv4, ["single_variant"], ["X-linked dominant"], ["TESTX"])]) # remove the known genes, so that the variants in unknown genes pass self.finder.known_genes = None self.assertEqual( sorted(self.finder.find_variants([snv1], "TEST2", family)), [(snv1, ["single_variant"], ["Monoallelic"], ["TEST2"]), (snv1, ["single_variant"], ["Mosaic"], ["TEST2"])]) # but variants without gene symbols still are excluded self.assertEqual(self.finder.find_variants([snv3], None, family), [])
class TestFamily(unittest.TestCase): """ """ def setUp(self): """ define a default Person object """ ID = "fam_ID" self.family = Family(ID) def test_add_father(self): """ test that add_father() works correctly """ ID = "parent_ID" path = "/home/parent.vcf" affected = "1" gender = "1" # check that adding a male father doesn't raise an error self.family.add_father(ID, path, affected, gender) # check that adding a father for a second time is fine, but adding # a different father raises an error self.family.add_father(ID, path, affected, gender) with self.assertRaises(ValueError): self.family.add_father("different_ID", path, affected, gender) # check that adding a female father raises an error self.setUp() gender = "2" with self.assertRaises(ValueError): self.family.add_father(ID, path, affected, gender) def test_add_mother(self): """ test that add_mother() works correctly """ ID = "parent_ID" path = "/home/parent.vcf" affected = "1" gender = "2" # check that adding a female mother doesn't raise an error self.family.add_mother(ID, path, affected, gender) # check that adding a mother for a second time is fine, but adding # a different mother raises an error self.family.add_mother(ID, path, affected, gender) with self.assertRaises(ValueError): self.family.add_mother("different_ID", path, affected, gender) # check that adding a male mother raises an error self.setUp() gender = "1" with self.assertRaises(ValueError): self.family.add_mother(ID, path, affected, gender) def test_add_child(self): """ check that add_child() works correctly """ # check that we can add one child self.family.add_child("child1", "/home/child1.vcf", "2", "1") self.assertEqual(len(self.family.children), 1) # check that adding multiple children works correctly self.family.add_child("child2", "/home/child2.vcf", "2", "2") self.family.add_child("child3", "/home/child3.vcf", "2", "1") self.assertEqual(len(self.family.children), 3) def test_set_child(self): """ test that set_child() works correctly """ # add one child self.family.add_child("child1", "/home/child1.vcf", "2", "1") # check that the child can be set correctly self.family.set_child() self.assertEqual(self.family.child, self.family.children[0]) # add more children self.family.add_child("child2", "/home/child2.vcf", "2", "1") self.family.add_child("child3", "/home/child3.vcf", "2", "2") # check that the child can be set correctly with multiple children self.family.set_child() self.assertIn(self.family.child, self.family.children) def test_set_child_examined(self): """ test that set_child_examined() works correctly """ # add one child self.family.add_child("child1", "/home/child1.vcf", "2", "1") # check that the child can be set correctly, and can be set as having # been examined self.family.set_child() self.family.set_child_examined() self.assertTrue(self.family.children[0].is_analysed()) self.assertIsNone(self.family.child) # add another child, and check that when we set the child, we now pick # up this child since the other one has previously been examined self.family.add_child("child2", "/home/child2.vcf", "2", "2") self.family.set_child() self.assertEqual(self.family.child, self.family.children[1]) # make sure that set_child_examined() doesn't default to None if we # have children left to analyse self.family.add_child("child3", "/home/child3.vcf", "2", "2") self.family.set_child() self.family.set_child_examined() self.assertIsNotNone(self.family.child) # and set child = None once we have analysed all the children self.family.set_child() self.family.set_child_examined() self.assertIsNone(self.family.child)