Reproducibility with normalize_total
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 2.6k
- Forks
- 779
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 27
Description
Hi,
We have encountered a bug regarding the reproducibility of the normalize_total in the latest version of scanpy==1.6.11. We also found this bug with scanpy==1.4.4.post1. This bug appears with an in-house dataset (containing 10x data and SMART-seq2 scaled data) and interestingly does not appear with the internal scanpy 10x 3k PBMC dataset.
Minimal code sample
def check_equal_adata_X(adata1, adata2):
print((adata1.X!=adata2.X).nnz==0)
tmp1 = adata1.X.todense()
tmp2 = adata2.X.todense()
print(np.array_equal(tmp1, tmp2))
print((tmp1 == tmp2).all())
adata_run1_concat = sc.read_h5ad("adata1.h5ad")
adata_run2_concat = sc.read_h5ad("adata2.h5ad")
check_equal_adata_X(adata_run1_concat, adata_run2_concat)
sc.pp.normalize_total(adata_run1_concat)
sc.pp.normalize_total(adata_run2_concat)
check_equal_adata_X(adata_run1_concat, adata_run2_concat)
Output:
True
True
True
False
False
False
Here is the code that fixes this bug.
adata_run1_concat = sc.read_h5ad("adata1.h5ad")
adata_run2_concat = sc.read_h5ad("adata2.h5ad")
check_equal_adata_X(adata_run1_concat, adata_run2_concat)
adata_run1_concat.X = adata_run1_concat.X.astype(np.float64)
adata_run2_concat.X = adata_run2_concat.X.astype(np.float64)
sc.pp.normalize_total(adata_run1_concat)
sc.pp.normalize_total(adata_run2_concat)
check_equal_adata_X(adata_run1_concat, adata_run2_concat)
Output:
True
True
True
True
True
True
Like I said, we tested also the "internal" scanpy 10x 3k PBMC dataset
sc.datasets.pbmc3k()
pbmc3k_1 = sc.read_h5ad("data/pbmc3k_raw.h5ad")
pbmc3k_2 = sc.read_h5ad("data/pbmc3k_raw.h5ad")
check_equal_adata_X(pbmc3k_1, pbmc3k_2)
sc.pp.normalize_total(pbmc3k_1)
sc.pp.normalize_total(pbmc3k_2)
check_equal_adata_X(pbmc3k_1, pbmc3k_2)
True
True
True
True
True
True
Versions
anndata 0.7.5
scanpy 1.6.1
sinfo 0.3.1
anndata 0.7.5
backcall 0.1.0
cycler 0.10.0
cython_runtime NA
dateutil 2.8.1
decorator 4.4.2
get_version 2.1
h5py 2.10.0
importlib_metadata 1.6.0
ipykernel 5.2.1
ipython_genutils 0.2.0
ipywidgets 7.5.1
jedi 0.17.0
joblib 0.14.1
kiwisolver 1.2.0
legacy_api_wrap 1.2
llvmlite 0.31.0
matplotlib 3.2.1
mpl_toolkits NA
natsort 7.0.1
numba 0.48.0
numexpr 2.7.1
numpy 1.18.2
packaging 20.3
pandas 1.0.3
parso 0.7.0
pexpect 4.8.0
pickleshare 0.7.5
pkg_resources NA
prompt_toolkit 3.0.5
ptyprocess 0.6.0
pygments 2.6.1
pyparsing 2.4.7
pytz 2019.3
scanpy 1.6.1
scipy 1.4.1
setuptools_scm NA
sinfo 0.3.1
six 1.14.0
sklearn 0.22.2.post1
storemagic NA
tables 3.6.1
tornado 6.0.4
tqdm 4.45.0
traitlets 4.3.3
wcwidth NA
zipp NA
zmq 19.0.0
IPython 7.13.0
jupyter_client 6.1.3
jupyter_core 4.6.3
notebook 6.0.3
Python 3.7.6 | packaged by conda-forge | (default, Mar 23 2020, 23:03:20) [GCC 7.3.0]
Linux-3.10.0-1127.18.2.el7.x86_64-x86_64-with-centos-7.8.2003-Core
36 logical CPU cores
Session information updated at 2021-01-27 17:16
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the minimal reproducible example and trace the sc.pp.normalize_total entry point, comparing inputs with the differing dtypes described in the issue. Check how the operation handles the provided sparse or mixed data, then run the reproduction to verify that equivalent inputs produce identical X values without manual float64 conversion.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- numpy, python
- Domain
- bioinformatics
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100