From fa3953710f702b7c532ac744e8f5ac99f02f8b55 Mon Sep 17 00:00:00 2001 From: Peter Kruczkiewicz Date: Fri, 23 Apr 2021 10:40:30 -0500 Subject: [PATCH 1/4] Add option to add Ct values to QC stats table from a Ct values table --- tests/data/io/ct.ods | Bin 0 -> 8116 bytes tests/data/io/ct.tsv | 4 ++++ tests/test_io_ct.py | 14 +++++++++++++ xlavir/cli.py | 2 ++ xlavir/io/ct.py | 45 ++++++++++++++++++++++++++++++++++++++++++ xlavir/qc/__init__.py | 3 +++ xlavir/xlavir.py | 7 +++++-- 7 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 tests/data/io/ct.ods create mode 100644 tests/data/io/ct.tsv create mode 100644 tests/test_io_ct.py create mode 100644 xlavir/io/ct.py diff --git a/tests/data/io/ct.ods b/tests/data/io/ct.ods new file mode 100644 index 0000000000000000000000000000000000000000..0ff63d77e56f7195be73d12d208be734f7a4959e GIT binary patch literal 8116 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 bool: + if df.empty: + logger.error(f'Ct values table is empty! No Ct values present!') + return False + n_rows, n_cols = df.shape + if n_cols != 2: + logger.error( + f'Ct values table expected to only have 2 columns, but {n_cols} were found with names: {", ".join(df.columns)}') + return False + return True + + +def read_ct_table(ct_path: Path) -> Dict[str, float]: + suffix = ct_path.suffix.lower() + if suffix == '.txt': + logger.warning(f'Trying to read "{ct_path.name}" as tab-delimited file with header.') + df = pd.read_table(ct_path) + elif suffix == '.tsv': + df = pd.read_table(ct_path) + elif suffix == '.ods': + df = pd.read_excel(ct_path, engine='odf') + elif suffix == '.csv': + df = pd.read_csv(ct_path) + elif suffix == '.xlsx': + df = pd.read_excel(ct_path) + else: + logger.error(f'Not sure how to parse Ct values table with extension "{suffix}". ' + f'Please provide a tab-delimited file (".tsv"), CSV (".csv"), ' + f'Excel file (".xlsx") or OpenDocument Spreadsheet (".ods").') + return {} + if validate_ct_table(df): + df.columns = ['sample', 'ct'] + logger.info(f'Read table with shape {df.shape} from "{ct_path}"') + return {row.sample: row.ct for row in df.itertuples()} + else: + return {} diff --git a/xlavir/qc/__init__.py b/xlavir/qc/__init__.py index f364591..34d9cce 100644 --- a/xlavir/qc/__init__.py +++ b/xlavir/qc/__init__.py @@ -12,6 +12,7 @@ def columns(low_coverage_threshold: int = 5) -> List[Tuple[str, str]]: return [ ('sample', 'Sample', 'Sample name'), + ('ct_value', 'Ct Value', 'Real-time PCR Ct value'), ( 'qc_status', 'QC Status', @@ -84,6 +85,7 @@ def report_format(df: pd.DataFrame, low_coverage_threshold: int = 5) -> pd.DataF def create_qc_stats_dataframe(sample_depth_info: Dict[str, mosdepth.MosdepthDepthInfo], sample_mapping_info: Dict[str, samtools.SamtoolsFlagstat], + sample_cts: Dict[str, float], quality_reqs: QualityRequirements): sample_names = set(sample_depth_info.keys()) | set(sample_mapping_info.keys()) logger.info(f'N samples: {len(sample_names)}') @@ -92,6 +94,7 @@ def create_qc_stats_dataframe(sample_depth_info: Dict[str, mosdepth.MosdepthDept depth_info = sample_depth_info[sample].dict() if sample in sample_depth_info else {} mapping_info = sample_mapping_info[sample].dict() if sample in sample_mapping_info else {} merged_stats_info[sample] = {**depth_info, **mapping_info} + merged_stats_info[sample]['ct_value'] = sample_cts.get(sample, None) df_stats = pd.DataFrame(merged_stats_info.values()) mask_pass_depth = (df_stats.median_coverage >= quality_reqs.min_median_depth) mask_pass_breadth = (df_stats.genome_coverage >= quality_reqs.min_genome_coverage) diff --git a/xlavir/xlavir.py b/xlavir/xlavir.py index e217d18..fdd485f 100644 --- a/xlavir/xlavir.py +++ b/xlavir/xlavir.py @@ -4,6 +4,7 @@ from typing import Optional, List from xlavir import qc +from xlavir.io import ct from xlavir.io.excel_sheet_dataframe import ExcelSheetDataFrame, SheetName from xlavir.tools import mosdepth, samtools, consensus, pangolin, variants from xlavir.tools.nextflow import exec_report @@ -14,7 +15,8 @@ def run(input_dir: Path, quality_reqs: Optional[qc.QualityRequirements], - pangolin_lineage_csv: Optional[Path] = None) -> List[ExcelSheetDataFrame]: + pangolin_lineage_csv: Optional[Path] = None, + ct_values_table: Optional[Path] = None) -> List[ExcelSheetDataFrame]: if quality_reqs: quality_reqs = qc.QualityRequirements() nf_exec_info = exec_report.get_info(input_dir) @@ -26,12 +28,13 @@ def run(input_dir: Path, if logger.level == logging.DEBUG: for sample, info in sample_mapping_info.items(): logger.debug(info.dict()) - + sample_cts = ct.read_ct_table(ct_values_table) if ct_values_table else {} sample_variants = variants.get_info(input_dir) dfs: List[ExcelSheetDataFrame] = [] df_stats = qc.create_qc_stats_dataframe(sample_depth_info, sample_mapping_info, + sample_cts=sample_cts, quality_reqs=quality_reqs) dfs.append(ExcelSheetDataFrame(sheet_name=SheetName.qc_stats.value, df=qc.report_format(df_stats, From 251cebb890eb209c26a20b28137e15c2daf15645 Mon Sep 17 00:00:00 2001 From: Peter Kruczkiewicz Date: Fri, 23 Apr 2021 10:42:25 -0500 Subject: [PATCH 2/4] Add Ct values xlsx test file --- tests/data/io/ct.xlsx | Bin 0 -> 4778 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/data/io/ct.xlsx diff --git a/tests/data/io/ct.xlsx b/tests/data/io/ct.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..138a255e5eb5606a18cddd781b792695f7e902f4 GIT binary patch literal 4778 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 Xf1XogeR2xIO91?%f`{tb&o%!8o`(%N literal 0 HcmV?d00001 From e9f31903ea28bbe8c57df4c29c2aea9c69e353cc Mon Sep 17 00:00:00 2001 From: Peter Kruczkiewicz Date: Fri, 23 Apr 2021 10:42:38 -0500 Subject: [PATCH 3/4] =?UTF-8?q?Bump=20version:=200.2.4=20=E2=86=92=200.3.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- setup.cfg | 2 +- setup.py | 2 +- xlavir/__init__.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.cfg b/setup.cfg index be33e66..b77590b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.2.4 +current_version = 0.3.0 commit = True tag = True diff --git a/setup.py b/setup.py index 600976c..4e6008f 100644 --- a/setup.py +++ b/setup.py @@ -58,6 +58,6 @@ test_suite='tests', tests_require=test_requirements, url='https://github.com/peterk87/xlavir', - version='0.2.4', + version='0.3.0', zip_safe=False, ) diff --git a/xlavir/__init__.py b/xlavir/__init__.py index d7c3fed..aa05088 100644 --- a/xlavir/__init__.py +++ b/xlavir/__init__.py @@ -2,4 +2,4 @@ __author__ = """Peter Kruczkiewicz""" __email__ = 'peter.kruczkiewicz@gmail.com' -__version__ = '0.2.4' +__version__ = '0.3.0' From 9b6c1df6faba7773a216b66b56161fb7405408f8 Mon Sep 17 00:00:00 2001 From: Peter Kruczkiewicz Date: Fri, 23 Apr 2021 10:47:42 -0500 Subject: [PATCH 4/4] Add odfpy dep to setup.py --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 4e6008f..3dd5b41 100644 --- a/setup.py +++ b/setup.py @@ -20,6 +20,7 @@ 'biopython', 'openpyxl', 'imageio', + 'odfpy', ] setup_requirements = ['pytest-runner', ]