Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/api/deprecated.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
:toctree: generated/

pp.subsample
pp.recipe_weinreb17
tl.louvain
tl.sim
pl.sim
Expand Down
13 changes: 2 additions & 11 deletions docs/api/preprocessing.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
.. currentmodule:: scanpy
```

Filtering of highly-variable genes, batch-effect correction, per-cell normalization, preprocessing recipes.
Filtering of highly-variable genes, batch-effect correction, per-cell normalization.

Any transformation of the data matrix that is not a _tool_. Other than _tools_, preprocessing steps usually don't return an easily interpretable annotation, but perform a basic transformation on the data matrix.

Expand Down Expand Up @@ -36,16 +36,7 @@ For visual quality control, see {func}`~scanpy.pl.highest_expr_genes` and
pp.downsample_counts
```

## Recipes

```{eval-rst}
.. autosummary::
:nosignatures:
:toctree: generated/

pp.recipe_zheng17
pp.recipe_seurat
```
For workflows using the removed legacy recipes, see {doc}`../how-to/legacy-recipes`.

(pp-data-integration)=

Expand Down
1 change: 1 addition & 0 deletions docs/how-to/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ This section contains short examples on how to perform specific tasks with scanp

```{toctree}
cell-cycle
legacy-recipes
knn-transformers
plotting-with-marsilea
```
58 changes: 58 additions & 0 deletions docs/how-to/legacy-recipes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Migrating from legacy preprocessing recipes

`sc.pp.recipe_seurat`, `sc.pp.recipe_zheng17`, and `sc.pp.recipe_weinreb17` have been removed.
Compose individual preprocessing functions to make the transformations and their parameters explicit.
{func}`scanpy.experimental.pp.recipe_pearson_residuals` is unaffected.

The examples below start from non-logarithmized counts and reproduce the final expression matrices of the former Seurat and Zheng recipes with their default arguments and the `ScanpyV1` preset.
They subset into a new `AnnData` object; start with `adata = adata.copy()` if you also need to preserve the input object.
Unlike the recipes, calling {func}`~scanpy.pp.log1p` directly on `.X` also records `.uns["log1p"]`.
Nondefault arguments, especially `log=False`, require separate consideration of the original transformation order.

## Seurat

```python
import scanpy as sc

sc.pp.filter_cells(adata, min_genes=200)
sc.pp.filter_genes(adata, min_cells=3)
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
hvg = sc.pp.highly_variable_genes(
adata, flavor="seurat", min_mean=0.0125, max_mean=3, min_disp=0.5, out=True
)
adata = adata[:, hvg["highly_variable"]].copy()
sc.pp.scale(adata, zero_center=True, max_value=10)
```

## Zheng et al. (2017)

```python
import scanpy as sc

sc.pp.filter_genes(adata, min_counts=1)
normalized = sc.pp.normalize_total(adata, out=True)
adata.X = normalized.normalized
adata.obs["n_counts_all"] = normalized.norm_factor
sc.pp.log1p(adata)
hvg = sc.pp.highly_variable_genes(
adata, flavor="cell_ranger", n_top_genes=1000, out=True
)
adata = adata[:, hvg["highly_variable"]].copy()
sc.pp.scale(adata, zero_center=True)
```

The normalization target is the median nonzero cell total before highly variable gene selection.
`n_counts_all` retains the former recipe's normalization factors (cell totals divided by that target), rather than raw counts.
Gene selection uses the log-normalized matrix, matching the former implementation.
With the default `log=True`, the recipe's second normalization was discarded when it restored its saved log-transformed layer; do not add a second normalization to this workflow.
To inspect gene dispersion, call {func}`~scanpy.pl.highly_variable_genes` on `hvg` before subsetting (`log=True` for Zheng, `log=False` for the default Seurat recipe).

## Weinreb et al. (2017)

There is no numerically equivalent replacement using only the standard preprocessing functions.
The former recipe optionally logged **before** normalization, excluded genes exceeding 5% of a cell's total, and scaled by the mean total over all genes.
It selected genes by mean and coefficient of variation, then computed PCA using population standard deviations plus `0.0001` for standardization.
In contrast, {func}`~scanpy.pp.scale` uses sample standard deviations, and {func}`~scanpy.pp.highly_variable_genes` uses different selection criteria.
For new analyses, explicitly choose {func}`~scanpy.pp.normalize_total`, {func}`~scanpy.pp.log1p`, {func}`~scanpy.pp.highly_variable_genes`, {func}`~scanpy.pp.scale`, and {func}`~scanpy.pp.pca` parameters appropriate to the data; this is a change of analysis, not an equivalent substitution.
To reproduce an existing Weinreb analysis exactly, retain the Scanpy version and parameters used for that analysis.
2 changes: 1 addition & 1 deletion docs/release-notes/1.13.0b1.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#### Miscellaneous changes

- Deprecate {func}`~scanpy.tl.sim`, {func}`~scanpy.pl.sim`, {func}`~scanpy.datasets.toggleswitch`, {func}`~scanpy.pp.recipe_weinreb17`, {func}`~scanpy.queries.gene_coordinates`, and the undocumented `sc.datasets.burczynski06`, `sc.tl.paga_compare_paths`, `sc.tl.paga_degrees`, `sc.tl.paga_expression_entropies`, and `sc.pl.paga_adjacency`, which have next to no users.
- Deprecate {func}`~scanpy.tl.sim`, {func}`~scanpy.pl.sim`, {func}`~scanpy.datasets.toggleswitch`, `scanpy.pp.recipe_weinreb17`, {func}`~scanpy.queries.gene_coordinates`, and the undocumented `sc.datasets.burczynski06`, `sc.tl.paga_compare_paths`, `sc.tl.paga_degrees`, `sc.tl.paga_expression_entropies`, and `sc.pl.paga_adjacency`, which have next to no users.
Remove unreachable code paths from {func}`~scanpy.tl.dpt` {smaller}`L Heumos` ({pr}`4390`)

#### Documentation
Expand Down
3 changes: 3 additions & 0 deletions docs/release-notes/4493.breaking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Remove `scanpy.pp.recipe_seurat`, `scanpy.pp.recipe_zheng17`, and `scanpy.pp.recipe_weinreb17` and their private implementation.
Use explicit preprocessing steps instead; see {doc}`/how-to/legacy-recipes` for migration examples and the numerical differences to consider for Weinreb workflows.
{func}`scanpy.experimental.pp.recipe_pearson_residuals` remains available.
30 changes: 11 additions & 19 deletions docs/tutorials/trajectories/paga-paul15.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -196,31 +196,23 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Apply a simple preprocessing recipe: {func}`scanpy.pp.recipe_zheng17`."
"Filter genes, normalize counts, select highly variable genes, and scale explicitly. This preserves the final expression matrix of the former default Zheng recipe: gene selection uses log-normalized values, with no renormalization after selection. See [the migration guide](../../how-to/legacy-recipes.md) for details."
]
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"running recipe zheng17\n",
"normalizing counts per cell\n",
" finished (0:00:00)\n",
"extracting highly variable genes\n",
" finished (0:00:00)\n",
"normalizing counts per cell\n",
" finished (0:00:00)\n",
" finished (0:00:00)\n"
]
}
],
"outputs": [],
"source": [
"sc.pp.recipe_zheng17(adata)"
"sc.pp.filter_genes(adata, min_counts=1)\n",
"sc.pp.normalize_total(adata, out={\"normalized\": \"X\", \"norm_factor\": \"obs.n_counts_all\"})\n",
"sc.pp.log1p(adata)\n",
"hvg = sc.pp.highly_variable_genes(\n",
" adata, flavor=\"cell_ranger\", n_top_genes=1000, out=True\n",
")\n",
"adata = adata[:, hvg[\"highly_variable\"]].copy()\n",
"sc.pp.scale(adata, zero_center=True)"
]
},
{
Expand Down
11 changes: 10 additions & 1 deletion src/scanpy/external/pp/_scanorama_integrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,16 @@ def scanorama_integrate(
>>> import scanpy as sc
>>> import scanpy.external as sce
>>> adata = sc.datasets.pbmc3k()
>>> sc.pp.recipe_zheng17(adata)
>>> sc.pp.filter_genes(adata, min_counts=1)
>>> sc.pp.normalize_total(
... adata, out={"normalized": "X", "norm_factor": "obs.n_counts_all"}
... )
>>> sc.pp.log1p(adata)
>>> hvg = sc.pp.highly_variable_genes(
... adata, flavor="cell_ranger", n_top_genes=1000, out=True
... )
>>> adata = adata[:, hvg["highly_variable"]].copy()
>>> sc.pp.scale(adata, zero_center=True)
>>> sc.pp.pca(adata)

We now arbitrarily assign a batch metadata variable to each cell
Expand Down
4 changes: 0 additions & 4 deletions src/scanpy/preprocessing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
)
from ._pca import PcaOut, PcaResult, pca
from ._qc import QcMetricsOut, QcMetricsResult, calculate_qc_metrics
from ._recipes import recipe_seurat, recipe_weinreb17, recipe_zheng17
from ._scale import ScaleOut, ScaleResult, scale
from ._scrublet import ScrubletOut, ScrubletResult, scrublet, scrublet_simulate_doublets
from ._simple import (
Expand Down Expand Up @@ -60,9 +59,6 @@
"normalize_shifted_clr",
"normalize_total",
"pca",
"recipe_seurat",
"recipe_weinreb17",
"recipe_zheng17",
"regress_out",
"sample",
"scale",
Expand Down
195 changes: 0 additions & 195 deletions src/scanpy/preprocessing/_recipes/__init__.py

This file was deleted.

Loading
Loading