From 29230e458adbc00654db745bb7b8d462ef3470cf Mon Sep 17 00:00:00 2001 From: "Seung-been \"Steven\" Lee" Date: Wed, 8 Jun 2022 10:23:06 +0900 Subject: [PATCH 1/8] Bump up version number --- CHANGELOG.rst | 3 +++ fuc/version.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index abc8678..aef7490 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,9 @@ Changelog ********* +0.35.0 (in development) +----------------------- + 0.34.0 (2022-06-08) ------------------- diff --git a/fuc/version.py b/fuc/version.py index cac7112..2670d05 100644 --- a/fuc/version.py +++ b/fuc/version.py @@ -1 +1 @@ -__version__ = '0.34.0' +__version__ = '0.35.0' From 0b90c895ab2a344b06b56dca8f94b1ab206086f4 Mon Sep 17 00:00:00 2001 From: "Seung-been \"Steven\" Lee" Date: Thu, 9 Jun 2022 10:02:07 +0900 Subject: [PATCH 2/8] Fix bug in `api.pyvcf.VcfFrame.pseudophase` --- CHANGELOG.rst | 2 ++ fuc/api/pyvcf.py | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index aef7490..f37419c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,6 +4,8 @@ Changelog 0.35.0 (in development) ----------------------- +* Fix bug in :meth:`api.pyvcf.VcfFrame.pseudophase` method. + 0.34.0 (2022-06-08) ------------------- diff --git a/fuc/api/pyvcf.py b/fuc/api/pyvcf.py index b5f74f8..4b6ca53 100644 --- a/fuc/api/pyvcf.py +++ b/fuc/api/pyvcf.py @@ -700,9 +700,9 @@ def gt_pseudophase(g): -------- >>> from fuc import pyvcf - >>> pyvcf.pseudophase('0/1') + >>> pyvcf.gt_pseudophase('0/1') '0|1' - >>> pyvcf.pseudophase('0/0:34:10,24') + >>> pyvcf.gt_pseudophase('0/0:34:10,24') '0|0:34:10,24' """ l = g.split(':') @@ -6463,7 +6463,7 @@ def pseudophase(self): 1 chr2 101 . T C . . . GT 1|1 """ def one_row(r): - r[9:] = r[9:].apply(pseudophase) + r[9:] = r[9:].apply(gt_pseudophase) return r df = self.df.apply(one_row, axis=1) return self.__class__(self.copy_meta(), df) From aceac640a0202c14a5b10f702dc6b003dac500ea Mon Sep 17 00:00:00 2001 From: "Seung-been \"Steven\" Lee" Date: Thu, 9 Jun 2022 17:22:00 +0900 Subject: [PATCH 3/8] Add new methods `pyvcf.VcfFrame.diploidize` and `pyvcf.gt_diploidize` --- CHANGELOG.rst | 1 + fuc/api/pyvcf.py | 95 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f37419c..daecd1b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,7 @@ Changelog ----------------------- * Fix bug in :meth:`api.pyvcf.VcfFrame.pseudophase` method. +* Add new methods :meth:`pyvcf.VcfFrame.diploidize` and :meth:`pyvcf.gt_diploidize`. 0.34.0 (2022-06-08) ------------------- diff --git a/fuc/api/pyvcf.py b/fuc/api/pyvcf.py index 4b6ca53..16a431e 100644 --- a/fuc/api/pyvcf.py +++ b/fuc/api/pyvcf.py @@ -447,6 +447,54 @@ def rescue_filtered_variants(vfs, format='GT'): merged_vf = merge(filtered_vfs, how='outer', format=format) return merged_vf +def gt_diploidize(g): + """ + For given genotype, return its diploid form. + + This method will ignore diploid genotypes (e.g. 0/1) and is therefore + only effective for haploid genotypes (e.g. genotypes from the X + chromosome for males). + + Parameters + ---------- + g : str + Sample genotype. + + Returns + ------- + bool + Diploid genotype. + + See Also + -------- + VcfFrame.diploidize + Diploidize VcfFrame. + + Examples + -------- + + >>> from fuc import pyvcf + >>> pyvcf.gt_diploidize('0') + '0/0' + >>> pyvcf.gt_diploidize('1') + '0/1' + >>> pyvcf.gt_diploidize('.') + './.' + >>> pyvcf.gt_diploidize('1:34') + '0/1:34' + >>> pyvcf.gt_diploidize('0/1:34') + '0/1:34' + >>> pyvcf.gt_diploidize('./.') + './.' + """ + if gt_ploidy(g) != 1: + return g + gt = g.split(':')[0] + if gt == '.': + return './' + g + else: + return '0/' + g + def gt_miss(g): """ For given genotype, return True if it has missing value. @@ -6378,6 +6426,53 @@ def compare(self, other): df = df[['Locus', 'Sample', 'Self', 'Other']] return df + def diploidize(self): + """ + Diploidize VcfFrame. + + Returns + ------- + VcfFrame + Diploidized VcfFrame. + + See Also + -------- + gt_diploidize + For given genotype, return its diploid form. + + Examples + -------- + + >>> from fuc import pyvcf + >>> data = { + ... 'CHROM': ['chrX', 'chrX'], + ... 'POS': [100, 101], + ... 'ID': ['.', '.'], + ... 'REF': ['G', 'T'], + ... 'ALT': ['A', 'C'], + ... 'QUAL': ['.', '.'], + ... 'FILTER': ['.', '.'], + ... 'INFO': ['.', '.'], + ... 'FORMAT': ['GT', 'GT'], + ... 'Male': ['0', '1'], + ... 'Female': ['0/0', '0/1'], + ... } + >>> vf = pyvcf.VcfFrame.from_dict([], data) + >>> vf.df + CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Male Female + 0 chrX 100 . G A . . . GT 0 0/0 + 1 chrX 101 . T C . . . GT 1 0/1 + >>> vf.diploidize().df + CHROM POS ID REF ALT QUAL FILTER INFO FORMAT Male Female + 0 chrX 100 . G A . . . GT 0/0 0/0 + 1 chrX 101 . T C . . . GT 0/1 0/1 + """ + def one_row(r): + r[9:] = r[9:].apply(gt_diploidize) + return r + df = self.df.apply(one_row, axis=1) + return self.__class__(self.copy_meta(), df) + def fetch(self, variant): """ Fetch the VCF row that matches specified variant. From ad298592828cddd6d69717e5787db333ccb8c035 Mon Sep 17 00:00:00 2001 From: "Seung-been \"Steven\" Lee" Date: Mon, 13 Jun 2022 16:18:01 +0900 Subject: [PATCH 4/8] Update `api.pyvcf.VcfFrame.get_af`: * Update :meth:`api.pyvcf.VcfFrame.get_af` method to provide more informative error message. --- CHANGELOG.rst | 1 + fuc/api/pyvcf.py | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index daecd1b..55966a2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,7 @@ Changelog * Fix bug in :meth:`api.pyvcf.VcfFrame.pseudophase` method. * Add new methods :meth:`pyvcf.VcfFrame.diploidize` and :meth:`pyvcf.gt_diploidize`. +* Update :meth:`api.pyvcf.VcfFrame.get_af` method to provide more informative error message. 0.34.0 (2022-06-08) ------------------- diff --git a/fuc/api/pyvcf.py b/fuc/api/pyvcf.py index 16a431e..ae0c36b 100644 --- a/fuc/api/pyvcf.py +++ b/fuc/api/pyvcf.py @@ -6611,7 +6611,9 @@ def get_af(self, sample, variant): nan """ chrom, pos, ref, alt = common.parse_variant(variant) - r = self.df[(self.df.CHROM == chrom) & (self.df.POS == pos) & (self.df.REF == ref)] + + r = self.df[(self.df.CHROM == chrom) & (self.df.POS == pos) & + (self.df.REF == ref)] try: i = r.FORMAT.values[0].split(':').index('AF') @@ -6623,7 +6625,9 @@ def get_af(self, sample, variant): if alt in alts: j = r.ALT.values[0].split(',').index(alt) else: - raise ValueError(f'ALT allele not found, possible choices: {alts}') + message = (f"Position {chrom}-{pos}-{ref} does not have '{alt}' " + f"as ALT allele, possible choices: {alts}") + raise ValueError(message) field = r[sample].values[0].split(':')[i] From 3bdda8858d683c085b9ae23a78b360551d468de9 Mon Sep 17 00:00:00 2001 From: "Seung-been \"Steven\" Lee" Date: Mon, 13 Jun 2022 17:14:24 +0900 Subject: [PATCH 5/8] Update `api.pyvcf.VcfFrame.get_af`: * Update :meth:`api.pyvcf.VcfFrame.get_af` method to handle situations where there are multiple records with the same ``REF`` allele. --- CHANGELOG.rst | 2 +- fuc/api/pyvcf.py | 62 +++++++++++++++++++++++++++++------------------- 2 files changed, 38 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 55966a2..104589f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,7 +6,7 @@ Changelog * Fix bug in :meth:`api.pyvcf.VcfFrame.pseudophase` method. * Add new methods :meth:`pyvcf.VcfFrame.diploidize` and :meth:`pyvcf.gt_diploidize`. -* Update :meth:`api.pyvcf.VcfFrame.get_af` method to provide more informative error message. +* Update :meth:`api.pyvcf.VcfFrame.get_af` method to handle situations where there are multiple records with the same ``REF`` allele. 0.34.0 (2022-06-08) ------------------- diff --git a/fuc/api/pyvcf.py b/fuc/api/pyvcf.py index ae0c36b..60e372c 100644 --- a/fuc/api/pyvcf.py +++ b/fuc/api/pyvcf.py @@ -6567,7 +6567,10 @@ def get_af(self, sample, variant): """ Get allele fraction for a pair of sample and variant. - The method will return ``numpy.nan`` if the value is missing. + The method will return ``numpy.nan`` when: + + 1. variant is absent, or + 2. variant is present but there is no ``AF`` in the ``FORMAT`` column Parameters ---------- @@ -6586,34 +6589,48 @@ def get_af(self, sample, variant): >>> from fuc import pyvcf, common >>> data = { - ... 'CHROM': ['chr1', 'chr1', 'chr1', 'chr1'], - ... 'POS': [100, 101, 102, 103], - ... 'ID': ['.', '.', '.', '.'], - ... 'REF': ['A', 'G', 'A', 'C'], - ... 'ALT': ['C', 'T', 'G', 'G,A'], - ... 'QUAL': ['.', '.', '.', '.'], - ... 'FILTER': ['.', '.', '.', '.'], - ... 'INFO': ['.', '.', '.', '.'], - ... 'FORMAT': ['GT:AD:AF', 'GT:AD:AF', 'GT:AF', 'GT:AD:AF'], - ... 'A': ['0/1:12,15:0.444,0.556', '0/0:32,1:0.970,0.030', '0/1:.', './.:.:.'], - ... 'B': ['0/1:13,17:0.433,0.567', '0/1:14,15:0.483,0.517', './.:.', '1/2:0,11,17:0.000,0.393,0.607'], + ... 'CHROM': ['chr1', 'chr1', 'chr1', 'chr1', 'chr1'], + ... 'POS': [100, 100, 101, 102, 103], + ... 'ID': ['.', '.', '.', '.', '.'], + ... 'REF': ['A', 'A', 'G', 'A', 'C'], + ... 'ALT': ['C', 'T', 'T', 'G', 'G,A'], + ... 'QUAL': ['.', '.', '.', '.', '.'], + ... 'FILTER': ['.', '.', '.', '.', '.'], + ... 'INFO': ['.', '.', '.', '.', '.'], + ... 'FORMAT': ['GT:AD:AF', 'GT:AD:AF', 'GT:AD:AF', 'GT:AF', 'GT:AD:AF'], + ... 'A': ['0/1:12,15:0.444,0.556', '0/0:31,0:1.000,0.000', '0/0:32,1:0.970,0.030', '0/1:.', './.:.:.'], + ... 'B': ['0/0:29,0:1.000,0.000', '0/1:13,17:0.433,0.567', '0/1:14,15:0.483,0.517', './.:.', '1/2:0,11,17:0.000,0.393,0.607'], ... } >>> vf = pyvcf.VcfFrame.from_dict([], data) >>> vf.df CHROM POS ID REF ALT QUAL FILTER INFO FORMAT A B - 0 chr1 100 . A C . . . GT:AD:AF 0/1:12,15:0.444,0.556 0/1:13,17:0.433,0.567 - 1 chr1 101 . G T . . . GT:AD:AF 0/0:32,1:0.970,0.030 0/1:14,15:0.483,0.517 - 2 chr1 102 . A G . . . GT:AF 0/1:. ./.:. - 3 chr1 103 . C G,A . . . GT:AD:AF ./.:.:. 1/2:0,11,17:0.000,0.393,0.607 + 0 chr1 100 . A C . . . GT:AD:AF 0/1:12,15:0.444,0.556 0/0:29,0:1.000,0.000 + 1 chr1 100 . A T . . . GT:AD:AF 0/0:31,0:1.000,0.000 0/1:13,17:0.433,0.567 + 2 chr1 101 . G T . . . GT:AD:AF 0/0:32,1:0.970,0.030 0/1:14,15:0.483,0.517 + 3 chr1 102 . A G . . . GT:AF 0/1:. ./.:. + 4 chr1 103 . C G,A . . . GT:AD:AF ./.:.:. 1/2:0,11,17:0.000,0.393,0.607 >>> vf.get_af('A', 'chr1-100-A-C') 0.556 - >>> vf.get_af('B', 'chr1-102-A-G') + >>> vf.get_af('A', 'chr1-100-A-T') + 0.0 + >>> vf.get_af('B', 'chr1-100-A-T') + 0.567 + >>> vf.get_af('B', 'chr1-100-A-G') # does not exist nan + >>> vf.get_af('B', 'chr1-102-A-G') # missing AF data + nan + >>> vf.get_af('B', 'chr1-103-C-A') # multiallelic locus + 0.607 """ chrom, pos, ref, alt = common.parse_variant(variant) - r = self.df[(self.df.CHROM == chrom) & (self.df.POS == pos) & - (self.df.REF == ref)] + i = self.df.apply(lambda r: ((r.CHROM == chrom) & (r.POS == pos) & + (r.REF == ref) & (alt in r.ALT.split(','))), axis=1) + + if i.any(): + r = self.df[i] + else: + return np.nan try: i = r.FORMAT.values[0].split(':').index('AF') @@ -6622,12 +6639,7 @@ def get_af(self, sample, variant): alts = r.ALT.values[0].split(',') - if alt in alts: - j = r.ALT.values[0].split(',').index(alt) - else: - message = (f"Position {chrom}-{pos}-{ref} does not have '{alt}' " - f"as ALT allele, possible choices: {alts}") - raise ValueError(message) + j = r.ALT.values[0].split(',').index(alt) field = r[sample].values[0].split(':')[i] From 9fced452bb6ddfd59ca98b464922f9830d3901d9 Mon Sep 17 00:00:00 2001 From: Seung-been Lee Date: Mon, 13 Jun 2022 19:55:55 +0900 Subject: [PATCH 6/8] Update docs --- CHANGELOG.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 104589f..36b63a5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -4,9 +4,9 @@ Changelog 0.35.0 (in development) ----------------------- -* Fix bug in :meth:`api.pyvcf.VcfFrame.pseudophase` method. +* Fix bug in :meth:`pyvcf.VcfFrame.pseudophase` method. * Add new methods :meth:`pyvcf.VcfFrame.diploidize` and :meth:`pyvcf.gt_diploidize`. -* Update :meth:`api.pyvcf.VcfFrame.get_af` method to handle situations where there are multiple records with the same ``REF`` allele. +* Update :meth:`pyvcf.VcfFrame.get_af` method to handle situations where there are multiple records with the same ``REF`` allele. 0.34.0 (2022-06-08) ------------------- From 6b43829fffd61405e2558f8ddc33adb68f1053ae Mon Sep 17 00:00:00 2001 From: "Seung-been \"Steven\" Lee" Date: Wed, 6 Jul 2022 15:52:37 +0900 Subject: [PATCH 7/8] Add `pymaf.MafFrame.plot_regplot_tmb`: * Add new method :meth:`pymaf.MafFrame.plot_regplot_tmb`. * Rename :meth:`pyvcf.VcfFrame.plot_regplot` method to :meth:`pyvcf.VcfFrame.plot_regplot_tmb` and :meth:`pymaf.MafFrame.plot_regplot` method to :meth:`pymaf.MafFrame.plot_regplot_gene`. --- CHANGELOG.rst | 2 ++ fuc/api/pymaf.py | 91 ++++++++++++++++++++++++++++++++++++++++++++++-- fuc/api/pyvcf.py | 11 ++++-- 3 files changed, 100 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 36b63a5..b39f97e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,6 +7,8 @@ Changelog * Fix bug in :meth:`pyvcf.VcfFrame.pseudophase` method. * Add new methods :meth:`pyvcf.VcfFrame.diploidize` and :meth:`pyvcf.gt_diploidize`. * Update :meth:`pyvcf.VcfFrame.get_af` method to handle situations where there are multiple records with the same ``REF`` allele. +* Add new method :meth:`pymaf.MafFrame.plot_regplot_tmb`. +* Rename :meth:`pyvcf.VcfFrame.plot_regplot` method to :meth:`pyvcf.VcfFrame.plot_regplot_tmb` and :meth:`pymaf.MafFrame.plot_regplot` method to :meth:`pymaf.MafFrame.plot_regplot_gene`. 0.34.0 (2022-06-08) ------------------- diff --git a/fuc/api/pymaf.py b/fuc/api/pymaf.py index b666736..cefbaa3 100644 --- a/fuc/api/pymaf.py +++ b/fuc/api/pymaf.py @@ -1295,7 +1295,7 @@ def plot_genepair( return ax - def plot_regplot( + def plot_regplot_gene( self, af, group_col, a, b, a_size=None, b_size=None, genes=None, count=10, to_csv=None, ax=None, figsize=None, **kwargs ): @@ -1353,7 +1353,7 @@ def plot_regplot( >>> annot_file = '~/fuc-data/tcga-laml/tcga_laml_annot.tsv' >>> mf = pymaf.MafFrame.from_file(maf_file) >>> af = common.AnnFrame.from_file(annot_file, sample_col=0) - >>> mf.plot_regplot(af, 'FAB_classification', 'M1', 'M2') + >>> mf.plot_regplot_gene(af, 'FAB_classification', 'M1', 'M2') Results for M2 ~ M1: R^2 = 0.43 P = 3.96e-02 @@ -1398,6 +1398,93 @@ def plot_regplot( return ax + def plot_regplot_tmb( + self, af, subject_col, group_col, a, b, ax=None, figsize=None, + **kwargs + ): + """ + Create a scatter plot with a linear regression model fit visualizing + correlation between TMB in two sample groups. + + The method will automatically calculate and print summary statistics + including R-squared and p-value. + + Parameters + ---------- + af : AnnFrame + AnnFrame containing sample annotation data. + subject_col : str + AnnFrame column containing sample subject information. + group_col : str + AnnFrame column containing sample group information. + a, b : str + Sample group names. + ax : matplotlib.axes.Axes, optional + Pre-existing axes for the plot. Otherwise, crete a new one. + figsize : tuple, optional + Width, height in inches. Format: (float, float). + kwargs + Other keyword arguments will be passed down to + :meth:`seaborn.regplot`. + + Returns + ------- + matplotlib.axes.Axes + The matplotlib axes containing the plot. + + See Also + -------- + fuc.api.pyvcf.VcfFrame.plot_regplot_tmb + Similar method for the :meth:`fuc.api.pyvcf.VcfFrame` class. + + Examples + -------- + + .. plot:: + + >>> import matplotlib.pyplot as plt + >>> from fuc import common, pymaf, pyvcf + >>> common.load_dataset('pyvcf') + >>> vcf_file = '~/fuc-data/pyvcf/normal-tumor.vcf' + >>> annot_file = '~/fuc-data/pyvcf/normal-tumor-annot.tsv' + >>> vf = pyvcf.VcfFrame.from_file(vcf_file) + >>> af = common.AnnFrame.from_file(annot_file, sample_col='Sample') + >>> mf = pymaf.MafFrame.from_vcf(vf) + >>> mf.plot_regplot_tmb(af, 'Patient', 'Tissue', 'Normal', 'Tumor') + Results for Tumor ~ Normal: + R^2 = 0.01 + P = 7.17e-01 + >>> plt.tight_layout() + """ + d = self.df.value_counts('Tumor_Sample_Barcode').to_dict() + + df = af.df[af.df[group_col].isin([a, b])][[group_col, subject_col]] + df = df.reset_index().pivot(index=subject_col, columns=group_col, + values=af.df.index.name) + + def one_row(r): + for col in [a, b]: + if r[col] in d: + r[col] = d[r[col]] + else: + r[col] = 0 + return r + + df = df.apply(one_row, axis=1) + + if ax is None: + fig, ax = plt.subplots(figsize=figsize) + + sns.regplot(x=a, y=b, data=df, ax=ax, **kwargs) + + # Print summary statistics including R-squared and p-value. + results = smf.ols(f'{b} ~ {a}', data=df).fit() + print(f"Results for {b} ~ {a}:") + print(f'R^2 = {results.rsquared:.2f}') + print(f' P = {results.f_pvalue:.2e}') + + return ax + def plot_interactions( self, count=10, cmap=None, ax=None, figsize=None, **kwargs ): diff --git a/fuc/api/pyvcf.py b/fuc/api/pyvcf.py index 60e372c..4efdb28 100644 --- a/fuc/api/pyvcf.py +++ b/fuc/api/pyvcf.py @@ -3520,7 +3520,9 @@ def plot_tmb( return ax - def plot_regplot(self, a, b, ax=None, figsize=None, **kwargs): + def plot_regplot_tmb( + self, a, b, ax=None, figsize=None, **kwargs + ): """ Create a scatter plot with a linear regression model fit visualizing correlation between TMB in two sample groups. @@ -3545,6 +3547,11 @@ def plot_regplot(self, a, b, ax=None, figsize=None, **kwargs): matplotlib.axes.Axes The matplotlib axes containing the plot. + See Also + -------- + fuc.api.pymaf.MafFrame.plot_regplot_tmb + Similar method for the :meth:`fuc.api.pymaf.MafFrame` class. + Examples -------- @@ -3560,7 +3567,7 @@ def plot_regplot(self, a, b, ax=None, figsize=None, **kwargs): >>> normal.name = 'Normal' >>> tumor = af.df[af.df.Tissue == 'Tumor'].index >>> tumor.name = 'Tumor' - >>> vf.plot_regplot(normal, tumor) + >>> vf.plot_regplot_tmb(normal, tumor) Results for B ~ A: R^2 = 0.01 P = 7.17e-01 From 12e103ec5feb5fdb3381fd3fe428d2d4ba67bccc Mon Sep 17 00:00:00 2001 From: "Seung-been \"Steven\" Lee" Date: Tue, 12 Jul 2022 08:25:33 +0900 Subject: [PATCH 8/8] Update docs --- CHANGELOG.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b39f97e..e809a45 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,8 +1,8 @@ Changelog ********* -0.35.0 (in development) ------------------------ +0.35.0 (2022-07-12) +------------------- * Fix bug in :meth:`pyvcf.VcfFrame.pseudophase` method. * Add new methods :meth:`pyvcf.VcfFrame.diploidize` and :meth:`pyvcf.gt_diploidize`.