Error in running scrublet
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 2.6k
- Forks
- 779
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 27
Description
Please make sure these conditions are met
- I have checked that this issue has not already been reported.
- I have confirmed this bug exists on the latest version of scanpy.
- (optional) I have confirmed this bug exists on the main branch of scanpy.
What happened?
Hi, I am running the Scrublet function to remove doublets.
the annadata was generated by concat several samples from two articles:
[1] Wu F, Fan J, He Y, et al. Single-cell profiling of tumor heterogeneity and the microenvironment in advanced non-small cell lung cancer[J]. Nature Communications, 2021, 12(1): 2540.
[2] Wang Y, Chen D, Liu Y, et al. Multidirectional characterization of cellular composition and spatial architecture in human multiple primary lung cancers[J]. Cell Death & Disease, 2023, 14(7): 462.
However, there was an error I cann't handle.
Minimal code sample
# 240520鳞癌,不用
# lung_ti_p1 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047623_P1_T_R_I'), var_names='gene_symbols', cache=True, cache_compression='gzip')
# lung_tm_p1 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047624_P1_N_R_I'), var_names='gene_symbols', cache=True, cache_compression='gzip')
# lung_ni_p1 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047624_P1_N_R_I'), var_names='gene_symbols', cache=True, cache_compression='gzip')
# lung_nm_p1 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047626_P1_N_R_M'), var_names='gene_symbols', cache=True, cache_compression='gzip')
# 240520 去掉癌旁,只用癌
lung_ti_p2 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047627_P2_T_R_I'), var_names='gene_symbols', cache=True, cache_compression='gzip')
lung_tm_p2 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047629_P2_T_R_M'), var_names='gene_symbols', cache=True, cache_compression='gzip')
# lung_ni_p2 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047628_P2_N_R_I'), var_names='gene_symbols', cache=True, cache_compression='gzip')
# lung_nm_p2 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047630_P2_N_R_M'), var_names='gene_symbols', cache=True, cache_compression='gzip')
lung_ti1_P3 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047631_P8_T1_R_I'), var_names='gene_symbols', cache=True, cache_compression='gzip')
lung_tm1_P3 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047634_P8_T1_R_M'), var_names='gene_symbols', cache=True, cache_compression='gzip')
# lung_ni_P3 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047633_P8_N_R_I'), var_names='gene_symbols', cache=True, cache_compression='gzip')
# lung_nm_P3 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047636_P8_N_R_M'), var_names='gene_symbols', cache=True, cache_compression='gzip')
lung_ti2_P3 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047632_P8_T2_R_I'), var_names='gene_symbols', cache=True, cache_compression='gzip')
lung_tm2_P3 = sc.read_10x_mtx(os.path.join(root, 'GSE200972_RAW', 'GSM6047635_P8_T2_R_M'), var_names='gene_symbols', cache=True, cache_compression='gzip')
# https://cloud.tencent.com/developer/article/2385592这儿得转置一下,不然不对
lung_ti_p4 = sc.read_text(os.path.join(root, 'GSE200972_RAW', 'GSM6047637_P4-2T1_matrix.tsv.gz')).T
# lung_ni_p4 = sc.read_text(os.path.join(root, 'GSE200972_RAW', 'GSM6047638_P4-2T2_matrix.tsv.gz')).T
lung_ts1_p4 = sc.read_text(os.path.join(root, 'GSE200972_RAW', 'GSM6047639_P4-2N_matrix.tsv.gz')).T
lung_ts2_p4 = sc.read_text(os.path.join(root, 'GSE200972_RAW', 'GSM6047640_P4-1T_matrix.tsv.gz')).T
# lung_ns_p4 = sc.read_text(os.path.join(root, 'GSE200972_RAW', 'GSM6047641_P4-1N_matrix.tsv.gz')).T
# 240520
lung_P5 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453580_P5_exp.txt.gz').T
lung_P8 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453583_P8_exp.txt.gz').T
lung_P16 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453591_P16_exp.txt.gz').T
lung_P24 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453599_P24_exp.txt.gz').T
lung_P28 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453603_P28_exp.txt.gz').T
lung_P38 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453613_P38_exp.txt.gz').T
lung_P20 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453595_P20_exp.txt.gz').T
lung_P9 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453584_P9_exp.txt.gz').T
lung_P33 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453608_P33_exp.txt.gz').T
lung_P13 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453588_P13_exp.txt.gz').T
lung_P21 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453596_P21_exp.txt.gz').T
lung_P32 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453607_P32_exp.txt.gz').T
lung_P35 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453610_P35_exp.txt.gz').T
lung_P2 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453577_P2_exp.txt.gz').T
lung_P39 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453614_P39_exp.txt.gz').T
lung_P29 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453604_P29_exp.txt.gz').T
lung_P34 = sc.read_text('D:\课题\博士课题\单细胞分析\GSE148071_RAW\GSM4453609_P34_exp.txt.gz').T
alldata = lung_ti_p2.concatenate(lung_tm_p2,
lung_ti1_P3,lung_tm1_P3,lung_ti2_P3,lung_tm2_P3,
lung_ti_p4,lung_ts1_p4,lung_ts2_p4,
lung_P2, lung_P5, lung_P8, lung_P9,
lung_P13, lung_P16,
lung_P20, lung_P21, lung_P24, lung_P28, lung_P29,
lung_P32, lung_P33, lung_P34, lung_P35, lung_P38, lung_P39,
batch_categories = ["TI-P2", "TM-P2",
"TI1-P3", 'TM1-P3', 'TI2-P3', 'TM2-P3',
"TI-P4",'TS1-P4','TS2-P4',
'lung_P2', 'lung_P5', 'lung_P8', 'lung_P9',
'lung_P13', 'lung_P16',
'lung_P20', 'lung_P21', 'lung_P24', 'lung_P28', 'lung_P29',
'lung_P32', 'lung_P33', 'lung_P34', 'lung_P35', 'lung_P38', 'lung_P39'],
join='outer')
print('Begin of post doublets removal and QC plot')
sc.pp.scrublet(alldata, n_neighbors=10)
alldata = alldata[alldata.obs['predicted_doublet']==False, :].copy()
n1 = alldata.shape[0]
print(f'Cells retained after scrublet: {n1}, {n0-n1} removed.')
print(f'End of post doublets removal and QC plots.')
Error output
Begin of post doublets removal and QC plot
Running Scrublet
normalizing counts per cell
C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\scanpy\preprocessing\_normalization.py:233: UserWarning: Some cells have zero counts
warn(UserWarning("Some cells have zero counts"))
finished (0:00:00)
WARNING: adata.X seems to be already log-transformed.
extracting highly variable genes
C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\scanpy\preprocessing\_simple.py:377: RuntimeWarning: invalid value encountered in log1p
np.log1p(X, out=X)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[59], line 2
1 print('Begin of post doublets removal and QC plot')
----> 2 sc.pp.scrublet(alldata, n_neighbors=10)
3 alldata = alldata[alldata.obs['predicted_doublet']==False, :].copy()
4 n1 = alldata.shape[0]
File C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\legacy_api_wrap\__init__.py:80, in legacy_api.<locals>.wrapper.<locals>.fn_compatible(*args_all, **kw)
77 @wraps(fn)
78 def fn_compatible(*args_all: P.args, **kw: P.kwargs) -> R:
79 if len(args_all) <= n_positional:
---> 80 return fn(*args_all, **kw)
82 args_pos: P.args
83 args_pos, args_rest = args_all[:n_positional], args_all[n_positional:]
File C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\scanpy\preprocessing\_scrublet\__init__.py:282, in scrublet(adata, adata_sim, batch_key, sim_doublet_ratio, expected_doublet_rate, stdev_doublet_rate, synthetic_doublet_umi_subsampling, knn_dist_metric, normalize_variance, log_transform, mean_center, n_prin_comps, use_approx_neighbors, get_doublet_neighbor_parents, n_neighbors, threshold, verbose, copy, random_state)
279 adata.uns["scrublet"]["batched_by"] = batch_key
281 else:
--> 282 scrubbed = _run_scrublet(adata_obs, adata_sim)
284 # Copy outcomes to input object from our processed version
286 adata.obs["doublet_score"] = scrubbed["obs"]["doublet_score"]
File C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\scanpy\preprocessing\_scrublet\__init__.py:204, in scrublet.<locals>._run_scrublet(ad_obs, ad_sim)
201 # HVG process needs log'd data.
203 logged = pp.log1p(ad_obs, copy=True)
--> 204 pp.highly_variable_genes(logged)
205 ad_obs = ad_obs[:, logged.var["highly_variable"]].copy()
207 # Simulate the doublets based on the raw expressions from the normalised
208 # and filtered object.
File C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\legacy_api_wrap\__init__.py:80, in legacy_api.<locals>.wrapper.<locals>.fn_compatible(*args_all, **kw)
77 @wraps(fn)
78 def fn_compatible(*args_all: P.args, **kw: P.kwargs) -> R:
79 if len(args_all) <= n_positional:
---> 80 return fn(*args_all, **kw)
82 args_pos: P.args
83 args_pos, args_rest = args_all[:n_positional], args_all[n_positional:]
File C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\scanpy\preprocessing\_highly_variable_genes.py:648, in highly_variable_genes(***failed resolving arguments***)
645 del min_disp, max_disp, min_mean, max_mean, n_top_genes
647 if batch_key is None:
--> 648 df = _highly_variable_genes_single_batch(
649 adata, layer=layer, cutoff=cutoff, n_bins=n_bins, flavor=flavor
650 )
651 else:
652 df = _highly_variable_genes_batched(
653 adata, batch_key, layer=layer, cutoff=cutoff, n_bins=n_bins, flavor=flavor
654 )
File C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\scanpy\preprocessing\_highly_variable_genes.py:281, in _highly_variable_genes_single_batch(adata, layer, cutoff, n_bins, flavor)
279 # all of the following quantities are "per-gene" here
280 df = pd.DataFrame(dict(zip(["means", "dispersions"], (mean, dispersion))))
--> 281 df["mean_bin"] = _get_mean_bins(df["means"], flavor, n_bins)
282 disp_stats = _get_disp_stats(df, flavor)
284 # actually do the normalization
File C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\scanpy\preprocessing\_highly_variable_genes.py:307, in _get_mean_bins(means, flavor, n_bins)
304 else:
305 raise ValueError('`flavor` needs to be "seurat" or "cell_ranger"')
--> 307 return pd.cut(means, bins=bins)
File C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\pandas\core\reshape\tile.py:258, in cut(x, bins, right, labels, retbins, precision, include_lowest, duplicates, ordered)
255 if sz == 0:
256 raise ValueError("Cannot cut empty array")
--> 258 rng = (nanops.nanmin(x), nanops.nanmax(x))
259 mn, mx = (mi + 0.0 for mi in rng)
261 if np.isinf(mn) or np.isinf(mx):
262 # GH 24314
File C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\pandas\core\nanops.py:147, in bottleneck_switch.__call__.<locals>.f(values, axis, skipna, **kwds)
145 result = alt(values, axis=axis, skipna=skipna, **kwds)
146 else:
--> 147 result = alt(values, axis=axis, skipna=skipna, **kwds)
149 return result
File C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\pandas\core\nanops.py:404, in _datetimelike_compat.<locals>.new_func(values, axis, skipna, mask, **kwargs)
401 if datetimelike and mask is None:
402 mask = isna(values)
--> 404 result = func(values, axis=axis, skipna=skipna, mask=mask, **kwargs)
406 if datetimelike:
407 result = _wrap_results(result, orig_values.dtype, fill_value=iNaT)
File C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\pandas\core\nanops.py:1089, in _nanminmax.<locals>.reduction(values, axis, skipna, mask)
1086 if values.size == 0:
1087 return _na_for_min_count(values, axis)
-> 1089 values, mask = _get_values(
1090 values, skipna, fill_value_typ=fill_value_typ, mask=mask
1091 )
1092 result = getattr(values, meth)(axis)
1093 result = _maybe_null_out(result, axis, mask, values.shape)
File C:\ProgramData\Anaconda3\envs\dl\lib\site-packages\pandas\core\nanops.py:316, in _get_values(values, skipna, fill_value, fill_value_typ, mask)
314 if datetimelike or _na_ok_dtype(dtype):
315 values = values.copy()
--> 316 np.putmask(values, mask, fill_value)
317 else:
318 # np.where will promote if needed
319 values = np.where(~mask, values, fill_value)
TypeError: putmask: first argument must be an array
Versions
scanpy 1.10.1
numpy 1.26.0
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 at scanpy/preprocessing/_scrublet/init.py and follow the call into scanpy/preprocessing/_highly_variable_genes.py shown in the traceback. Reproduce the failure with the supplied concatenation and inspect the zero-count and already-log-transformed warnings; done means determining whether this is a Scanpy bug or an invalid input condition and documenting a minimal reproducible case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- bioinformatics
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100