From 084194b4612623976cb5a46cd1b47f4afbe6fdec Mon Sep 17 00:00:00 2001 From: Stephen Fleming Date: Tue, 31 Oct 2023 11:55:37 -0400 Subject: [PATCH] Fix bugs with report generation across platforms (#302) --- cellbender/remove_background/posterior.py | 11 ++++++++-- cellbender/remove_background/report.py | 25 ++++++++++++++--------- cellbender/remove_background/run.py | 1 + 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/cellbender/remove_background/posterior.py b/cellbender/remove_background/posterior.py index c421713..d99e533 100644 --- a/cellbender/remove_background/posterior.py +++ b/cellbender/remove_background/posterior.py @@ -1518,7 +1518,9 @@ def __repr__(self): f'\n\ttotal_n_genes: {self.total_n_genes}' f'\n\tmatrix_shape: {self.matrix_shape}') - def get_m_indices(self, cell_inds: np.ndarray, gene_inds: np.ndarray) -> np.ndarray: + def get_m_indices(self, + cell_inds: Union[np.ndarray, torch.Tensor], + gene_inds: Union[np.ndarray, torch.Tensor]) -> Union[np.ndarray, torch.Tensor]: """Given arrays of cell indices and gene indices, suitable for a sparse matrix, convert them to 'm' index values. """ @@ -1528,7 +1530,12 @@ def get_m_indices(self, cell_inds: np.ndarray, gene_inds: np.ndarray) -> np.ndar if not ((gene_inds >= 0) & (gene_inds < self.total_n_genes)).all(): raise ValueError(f'Requested gene_inds out of range: ' f'{gene_inds[(gene_inds < 0) | (gene_inds >= self.total_n_genes)]}') - return cell_inds.astype(np.uint64) * self.total_n_genes + gene_inds.astype(np.uint64) + if type(cell_inds) == np.ndarray: + return cell_inds.astype(np.uint64) * self.total_n_genes + gene_inds.astype(np.uint64) + elif type(cell_inds) == torch.Tensor: + return cell_inds.type(torch.int64) * self.total_n_genes + gene_inds.type(torch.int64) + else: + raise ValueError('IndexConverter.get_m_indices received cell_inds of unkown object type') def get_ng_indices(self, m_inds: np.ndarray) -> Tuple[np.ndarray, np.ndarray]: """Given a list of 'm' index values, return two arrays: cell index values diff --git a/cellbender/remove_background/report.py b/cellbender/remove_background/report.py index f1a34cb..dfb5f90 100644 --- a/cellbender/remove_background/report.py +++ b/cellbender/remove_background/report.py @@ -16,6 +16,7 @@ import subprocess import datetime import os +import shutil import logging from typing import Dict, Optional @@ -42,26 +43,30 @@ def _run_notebook(file): - subprocess.run(f'cp {file} tmp.report.ipynb', shell=True) + shutil.copy(file, 'tmp.report.ipynb') subprocess.run(run_notebook_str(file='tmp.report.ipynb'), shell=True) - subprocess.run(f'rm tmp.report.ipynb', shell=True) + os.remove('tmp.report.ipynb') return 'tmp.report.nbconvert.ipynb' def _to_html(file, output) -> str: subprocess.run(to_html_str(file=file, output=output), shell=True) - subprocess.run(f'mv {file.replace(".ipynb", ".html")} {output}', shell=True) - subprocess.run(f'rm {file}', shell=True) + os.replace(file.replace(".ipynb", ".html"), output) + os.remove(file) return output def _postprocess_html(file: str, title: str): - with open(file, mode='r') as f: - html = f.read() - html = html.replace('tmp.report.nbconvert', - f'{title}') - with open(file, mode='w') as f: - f.write(html) + try: + with open(file, mode='r', encoding="utf8", errors="surrogateescape") as f: + html = f.read() + html = html.replace('tmp.report.nbconvert', + f'{title}') + with open(file, mode='w', encoding="utf8", errors="surrogateescape") as f: + f.write(html) + except: + logger.warning('Failed to overwrite default HTML report title. ' + 'This is purely aesthetic and does not affect output.') def run_notebook_make_html(file, output) -> str: diff --git a/cellbender/remove_background/run.py b/cellbender/remove_background/run.py index 42cf5b4..ca2a592 100644 --- a/cellbender/remove_background/run.py +++ b/cellbender/remove_background/run.py @@ -43,6 +43,7 @@ from typing import Tuple, Optional, Dict, Union import matplotlib +import matplotlib.backends.backend_pdf # issue #287 matplotlib.use('Agg') import matplotlib.pyplot as plt # This needs to be after matplotlib.use('Agg')