wf-transcriptomes-v202/bin/plot_aln_stats.py
2021-12-08 14:34:07 +00:00

187 lines
5.7 KiB
Python
Executable File

#!/usr/bin/env python
"""Plot a seqkit alignment stats file."""
import argparse
import warnings
import matplotlib
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import six
matplotlib.use('Agg')
with warnings.catch_warnings():
warnings.simplefilter("ignore")
import seaborn as sns
warnings.resetwarnings()
_ = sns
# Parse command line arguments:
parser = argparse.ArgumentParser(
description="""Plot a seqkit alignment stats file.""")
parser.add_argument(
'-r', metavar='report_pdf', type=str, help="Report PDF (stats.pdf).",
default="stats.pdf")
parser.add_argument(
'input', metavar='input_tsv', type=str, help="Input TSV.")
class Report:
"""Class for plotting utilities on the top of matplotlib.
Plots are saved in the specified file through the PDF backend.
"""
def __init__(self, pdf):
"""
Init Report with a matplotlib PdfPages instance.
:param self: object.
:param pdf: Output pdf.
:returns: The report object.
:rtype: Report
"""
self.pdf = pdf
self.plt = plt
self.pages = PdfPages(pdf)
def _set_properties_and_close(self, fig, title, xlab, ylab):
"""Set title, axis labels and close the figure.
:param self: object.
:param fig: The current figure.
:param title: Figure title.
:param xlab: X axis label.
:param ylab: Y axis label.
:returns: None
:rtype: object
"""
plt.xlabel(xlab)
plt.ylabel(ylab)
plt.title(title)
self.pages.savefig(fig)
plt.close(fig)
def plot_boxplots(self, data_map, title="", xlab="", ylab="",
xticks_rotation=0, xticks_fontsize=5):
"""Plot multiple pairs of data arrays.
:param self: object.
:param data_map:
A dictionary with labels as keys and lists as data values.
:param title: Figure title.
:param xlab: X axis label.
:param ylab: Y axis label.
:param xticks_rotation: Rotation value for x tick labels.
:param xticks_fontsize: Fontsize for x tick labels.
:returns: None
:rtype: object
"""
fig = plt.figure()
plt.boxplot(list(data_map.values()))
plt.xticks(np.arange(len(data_map)) + 1, data_map.keys(),
rotation=xticks_rotation, fontsize=xticks_fontsize)
self._set_properties_and_close(fig, title, xlab, ylab)
def plot_bars_simple(self, data_map, title="", xlab="", ylab="", alpha=0.6,
xticks_rotation=0, auto_limit=False):
"""Plot simple bar chart from input dictionary.
:param self: object.
:param data_map: A dictionary with labels as keys and data as values.
:param title: Figure title.
:param xlab: X axis label.
:param ylab: Y axis label.
:param alpha: Alpha value.
:param xticks_rotation: Rotation value for x tick labels.
:param auto_limit: Set y axis limits automatically.
:returns: None
:rtype: object
"""
fig = plt.figure()
labels = list(data_map.keys())
data = list(data_map.values())
positions = np.arange(len(labels))
plt.bar(positions, data, align='center', alpha=alpha)
plt.xticks(positions, labels, rotation=xticks_rotation)
if auto_limit:
low, high = min(data), max(data)
plt.ylim([(low - 0.5 * (high - low)), (high + 0.5 * (high - low))])
self._set_properties_and_close(fig, title, xlab, ylab)
def plot_histograms(self, data_map, title="", xlab="", ylab="", bins=50,
alpha=0.7, legend_loc='best', legend=True,
vlines=None):
"""Plot histograms of multiple data arrays.
:param self: object.
:param data_map:
A dictionary with labels as keys and data arrays as values.
:param title: Figure title.
:param xlab: X axis label.
:param ylab: Y axis label.
:param bins: Number of bins.
:param alpha: Transparency value for histograms.
:param legend_loc: Location of legend.
:param legend: Plot legend if True.
:param vlines:
Dictionary with labels and positions of vertical lines to draw.
:returns: None
:rtype: object
"""
fig = plt.figure()
for label, data in six.iteritems(data_map):
if len(data) > 0:
plt.hist(data, bins=bins, label=label, alpha=alpha)
if vlines is not None:
for label, pos in six.iteritems(vlines):
plt.axvline(x=pos, label=label)
if legend:
plt.legend(loc=legend_loc)
self._set_properties_and_close(fig, title, xlab, ylab)
def close(self):
"""Close PDF backend.
Do not forget to call this at the end of your
script or your output will be damaged!
:param self: object
:returns: None
:rtype: object
"""
self.pages.close()
if __name__ == '__main__':
args = parser.parse_args()
plotter = Report(args.r)
# Plot overview panel:
stats = pd.read_csv(args.input, sep="\t")
perc = stats[["PrimAlnPerc", "MultimapPerc"]].copy()
num = stats[["PrimAln", "SecAln", "SupAln", "Unmapped", "TotalReads",
"TotalRecords"]].copy()
perc.plot(kind='bar')
plt.title("Percent primary and multimapping reads")
plt.tight_layout()
plotter.pages.savefig()
num.plot(kind='bar')
plt.title("Number of alignment records")
plt.tight_layout()
plotter.pages.savefig()
plotter.close()