We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Documentation for percent_top= in scanpy.pp.calculate_qc_metrics is unclear and contradictory
### Please make sure these conditions are met

- [X] I have checked that this issue has not already been reported.
- [X] I have confirmed this bug exists on the latest version of scanpy.
- [X] (optional) I have confirmed this bug exists on the master branch of scanpy.

### What happened?

First, the argument is named "percent"_top, suggesting a fraction in the range [0,1] or at a stretch [0, 100].

Second, the description starts with "Which proportion", again suggesting a fraction.

But then, the description goes on to say that `percent_top=[50]` would use the 50 most expressed genes, NOT the 50% most expressed genes. So in the end, it's not a percentage but an absolute number.

This is further supported by the fact that the default values are `(50, 100, 200, 500)`, which are clearly not percentages.
See: https://github.com/scverse/scanpy/blob/585f58c9e4dd82dd7809a831538c4e230b008818/scanpy/preprocessing/_qc.py#L237


### Minimal code sample

```python
# No code, issue is in documentation
```


### Error output

_No response_

### Versions

<details>

```
-----
anndata     0.10.4
scanpy      1.9.6
-----
PIL                         10.0.0
anyio                       NA
arrow                       1.3.0
asttokens                   NA
attr                        23.1.0
attrs                       23.1.0
babel                       2.13.1
certifi                     2023.07.22
cffi                        1.16.0
charset_normalizer          3.2.0
comm                        0.2.0
cycler                      0.10.0
cython_runtime              NA
dateutil                    2.8.2
debugpy                     1.8.0
decorator                   5.1.1
defusedxml                  0.7.1
entrypoints                 0.4
executing                   2.0.1
fastjsonschema              NA
fqdn                        NA
h5py                        3.10.0
idna                        3.4
igraph                      0.10.8
ipykernel                   6.27.1
ipython_genutils            0.2.0
ipywidgets                  8.1.1
isoduration                 NA
jedi                        0.19.1
jinja2                      3.1.2
joblib                      1.3.2
json5                       NA
jsonpointer                 2.4
jsonschema                  4.20.0
jsonschema_specifications   NA
jupyter_server              1.24.0
jupyterlab_server           2.25.2
kiwisolver                  1.4.5
leidenalg                   0.10.1
llvmlite                    0.41.1
markupsafe                  2.1.3
matplotlib                  3.7.2
matplotlib_inline           0.1.6
mpl_toolkits                NA
mpmath                      1.3.0
natsort                     8.4.0
nbformat                    5.9.2
numba                       0.58.1
numpy                       1.25.2
packaging                   23.1
pandas                      2.1.4
parso                       0.8.3
patsy                       0.5.6
pexpect                     4.9.0
platformdirs                4.1.0
plotly                      5.18.0
prometheus_client           NA
prompt_toolkit              3.0.41
psutil                      5.9.6
ptyprocess                  0.7.0
pure_eval                   0.2.2
pycparser                   2.21
pydev_ipython               NA
pydevconsole                NA
pydevd                      2.9.5
pydevd_file_utils           NA
pydevd_plugins              NA
pydevd_tracing              NA
pygments                    2.16.1
pyparsing                   3.0.9
pytz                        2023.3.post1
referencing                 NA
requests                    2.31.0
rfc3339_validator           0.1.4
rfc3986_validator           0.1.1
rpds                        NA
scipy                       1.11.4
seaborn                     0.13.1
send2trash                  NA
session_info                1.0.0
simplejson                  3.19.1
six                         1.16.0
sklearn                     1.3.2
sniffio                     1.3.0
sparse                      0.14.0
stack_data                  0.6.3
statsmodels                 0.14.1
sympy                       1.12
terminado                   0.18.0
texttable                   1.7.0
threadpoolctl               3.2.0
torch                       2.1.2+cu121
torchgen                    NA
tornado                     6.4
tqdm                        4.66.1
traitlets                   5.14.0
typing_extensions           NA
uri_template                NA
urllib3                     2.0.4
wcwidth                     0.2.12
webcolors                   1.13
websocket                   1.7.0
yaml                        6.0.1
zmq                         24.0.1
-----
IPython             8.18.1
jupyter_client      7.4.9
jupyter_core        5.5.0
jupyterlab          3.6.5
notebook            6.5.6
-----
Python 3.11.3 (main, Aug 25 2023, 17:24:38) [GCC 11.4.0]
Linux-5.15.0-91-generic-x86_64-with-glibc2.35
-----
Session information updated at 2024-02-07 10:05
```

</details>


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `scanpy/preprocessing/_docs.py`
Content:
```
1 """Shared docstrings for preprocessing function parameters.
2 """
3 from __future__ import annotations
4 
5 doc_adata_basic = """\
6 adata
7     Annotated data matrix.\
8 """
9 
10 doc_expr_reps = """\
11 layer
12     If provided, use `adata.layers[layer]` for expression values instead
13     of `adata.X`.
14 use_raw
15     If True, use `adata.raw.X` for expression values instead of `adata.X`.\
16 """
17 
18 doc_mask_hvg = """\
19 mask
20     To run only on a certain set of genes given by a boolean array
21     or a string referring to an array in :attr:`~anndata.AnnData.var`.
22     By default, uses `.var['highly_variable']` if available, else everything.
23 use_highly_variable
24     Whether to use highly variable genes only, stored in
25     `.var['highly_variable']`.
26     By default uses them if they have been determined beforehand.
27 
28     .. deprecated:: 1.10.0
29        Use `mask` instead
30 """
31 
32 doc_obs_qc_args = """\
33 qc_vars
34     Keys for boolean columns of `.var` which identify variables you could
35     want to control for (e.g. "ERCC" or "mito").
36 percent_top
37     Which proportions of top genes to cover. If empty or `None` don't
38     calculate. Values are considered 1-indexed, `percent_top=[50]` finds
39     cumulative proportion to the 50th most expressed gene.\
40 """
41 
42 doc_qc_metric_naming = """\
43 expr_type
44     Name of kind of values in X.
45 var_type
46     The kind of thing the variables are.\
47 """
48 
49 doc_obs_qc_returns = """\
50 Observation level metrics include:
51 
52 `total_{var_type}_by_{expr_type}`
53     E.g. "total_genes_by_counts". Number of genes with positive counts in a cell.
54 `total_{expr_type}`
55     E.g. "total_counts". Total number of counts for a cell.
56 `pct_{expr_type}_in_top_{n}_{var_type}` – for `n` in `percent_top`
57     E.g. "pct_counts_in_top_50_genes". Cumulative percentage of counts
58     for 50 most expressed genes in a cell.
59 `total_{expr_type}_{qc_var}` – for `qc_var` in `qc_vars`
60     E.g. "total_counts_mito". Total number of counts for variables in
61     `qc_vars`.
62 `pct_{expr_type}_{qc_var}` – for `qc_var` in `qc_vars`
63     E.g. "pct_counts_mito". Proportion of total counts for a cell which
64     are mitochondrial.\
65 """
66 
67 doc_var_qc_returns = """\
68 Variable level metrics include:
69 
70 `total_{expr_type}`
71     E.g. "total_counts". Sum of counts for a gene.
72 `n_genes_by_{expr_type}`
73     E.g. "n_genes_by_counts". The number of genes with at least 1 count in a cell. Calculated for all cells.
74 `mean_{expr_type}`
75     E.g. "mean_counts". Mean expression over all cells.
76 `n_cells_by_{expr_type}`
77     E.g. "n_cells_by_counts". Number of cells this expression is
78     measured in.
79 `pct_dropout_by_{expr_type}`
80     E.g. "pct_dropout_by_counts". Percentage of cells this feature does
81     not appear in.\
82 """
83
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/scanpy/preprocessing/_docs.py b/scanpy/preprocessing/_docs.py
--- a/scanpy/preprocessing/_docs.py
+++ b/scanpy/preprocessing/_docs.py
@@ -34,9 +34,12 @@
     Keys for boolean columns of `.var` which identify variables you could
     want to control for (e.g. "ERCC" or "mito").
 percent_top
-    Which proportions of top genes to cover. If empty or `None` don't
-    calculate. Values are considered 1-indexed, `percent_top=[50]` finds
-    cumulative proportion to the 50th most expressed gene.\
+    List of ranks (where genes are ranked by expression) at which the cumulative
+    proportion of expression will be reported as a percentage. This can be used to
+    assess library complexity. Ranks are considered 1-indexed, and if empty or None
+    don't calculate.
+
+    E.g. `percent_top=[50]` finds cumulative proportion to the 50th most expressed gene.
 """
 
 doc_qc_metric_naming = """\

{"golden_diff": "diff --git a/scanpy/preprocessing/_docs.py b/scanpy/preprocessing/_docs.py\n--- a/scanpy/preprocessing/_docs.py\n+++ b/scanpy/preprocessing/_docs.py\n@@ -34,9 +34,12 @@\n     Keys for boolean columns of `.var` which identify variables you could\n     want to control for (e.g. \"ERCC\" or \"mito\").\n percent_top\n-    Which proportions of top genes to cover. If empty or `None` don't\n-    calculate. Values are considered 1-indexed, `percent_top=[50]` finds\n-    cumulative proportion to the 50th most expressed gene.\\\n+    List of ranks (where genes are ranked by expression) at which the cumulative\n+    proportion of expression will be reported as a percentage. This can be used to\n+    assess library complexity. Ranks are considered 1-indexed, and if empty or None\n+    don't calculate.\n+\n+    E.g. `percent_top=[50]` finds cumulative proportion to the 50th most expressed gene.\n \"\"\"\n \n doc_qc_metric_naming = \"\"\"\\\n", "issue": "Documentation for percent_top= in scanpy.pp.calculate_qc_metrics is unclear and contradictory\n### Please make sure these conditions are met\n\n- [X] I have checked that this issue has not already been reported.\n- [X] I have confirmed this bug exists on the latest version of scanpy.\n- [X] (optional) I have confirmed this bug exists on the master branch of scanpy.\n\n### What happened?\n\nFirst, the argument is named \"percent\"_top, suggesting a fraction in the range [0,1] or at a stretch [0, 100].\r\n\r\nSecond, the description starts with \"Which proportion\", again suggesting a fraction.\r\n\r\nBut then, the description goes on to say that `percent_top=[50]` would use the 50 most expressed genes, NOT the 50% most expressed genes. So in the end, it's not a percentage but an absolute number.\r\n\r\nThis is further supported by the fact that the default values are `(50, 100, 200, 500)`, which are clearly not percentages.\r\nSee: https://github.com/scverse/scanpy/blob/585f58c9e4dd82dd7809a831538c4e230b008818/scanpy/preprocessing/_qc.py#L237\r\n\n\n### Minimal code sample\n\n```python\n# No code, issue is in documentation\n```\n\n\n### Error output\n\n_No response_\n\n### Versions\n\n<details>\r\n\r\n```\r\n-----\r\nanndata     0.10.4\r\nscanpy      1.9.6\r\n-----\r\nPIL                         10.0.0\r\nanyio                       NA\r\narrow                       1.3.0\r\nasttokens                   NA\r\nattr                        23.1.0\r\nattrs                       23.1.0\r\nbabel                       2.13.1\r\ncertifi                     2023.07.22\r\ncffi                        1.16.0\r\ncharset_normalizer          3.2.0\r\ncomm                        0.2.0\r\ncycler                      0.10.0\r\ncython_runtime              NA\r\ndateutil                    2.8.2\r\ndebugpy                     1.8.0\r\ndecorator                   5.1.1\r\ndefusedxml                  0.7.1\r\nentrypoints                 0.4\r\nexecuting                   2.0.1\r\nfastjsonschema              NA\r\nfqdn                        NA\r\nh5py                        3.10.0\r\nidna                        3.4\r\nigraph                      0.10.8\r\nipykernel                   6.27.1\r\nipython_genutils            0.2.0\r\nipywidgets                  8.1.1\r\nisoduration                 NA\r\njedi                        0.19.1\r\njinja2                      3.1.2\r\njoblib                      1.3.2\r\njson5                       NA\r\njsonpointer                 2.4\r\njsonschema                  4.20.0\r\njsonschema_specifications   NA\r\njupyter_server              1.24.0\r\njupyterlab_server           2.25.2\r\nkiwisolver                  1.4.5\r\nleidenalg                   0.10.1\r\nllvmlite                    0.41.1\r\nmarkupsafe                  2.1.3\r\nmatplotlib                  3.7.2\r\nmatplotlib_inline           0.1.6\r\nmpl_toolkits                NA\r\nmpmath                      1.3.0\r\nnatsort                     8.4.0\r\nnbformat                    5.9.2\r\nnumba                       0.58.1\r\nnumpy                       1.25.2\r\npackaging                   23.1\r\npandas                      2.1.4\r\nparso                       0.8.3\r\npatsy                       0.5.6\r\npexpect                     4.9.0\r\nplatformdirs                4.1.0\r\nplotly                      5.18.0\r\nprometheus_client           NA\r\nprompt_toolkit              3.0.41\r\npsutil                      5.9.6\r\nptyprocess                  0.7.0\r\npure_eval                   0.2.2\r\npycparser                   2.21\r\npydev_ipython               NA\r\npydevconsole                NA\r\npydevd                      2.9.5\r\npydevd_file_utils           NA\r\npydevd_plugins              NA\r\npydevd_tracing              NA\r\npygments                    2.16.1\r\npyparsing                   3.0.9\r\npytz                        2023.3.post1\r\nreferencing                 NA\r\nrequests                    2.31.0\r\nrfc3339_validator           0.1.4\r\nrfc3986_validator           0.1.1\r\nrpds                        NA\r\nscipy                       1.11.4\r\nseaborn                     0.13.1\r\nsend2trash                  NA\r\nsession_info                1.0.0\r\nsimplejson                  3.19.1\r\nsix                         1.16.0\r\nsklearn                     1.3.2\r\nsniffio                     1.3.0\r\nsparse                      0.14.0\r\nstack_data                  0.6.3\r\nstatsmodels                 0.14.1\r\nsympy                       1.12\r\nterminado                   0.18.0\r\ntexttable                   1.7.0\r\nthreadpoolctl               3.2.0\r\ntorch                       2.1.2+cu121\r\ntorchgen                    NA\r\ntornado                     6.4\r\ntqdm                        4.66.1\r\ntraitlets                   5.14.0\r\ntyping_extensions           NA\r\nuri_template                NA\r\nurllib3                     2.0.4\r\nwcwidth                     0.2.12\r\nwebcolors                   1.13\r\nwebsocket                   1.7.0\r\nyaml                        6.0.1\r\nzmq                         24.0.1\r\n-----\r\nIPython             8.18.1\r\njupyter_client      7.4.9\r\njupyter_core        5.5.0\r\njupyterlab          3.6.5\r\nnotebook            6.5.6\r\n-----\r\nPython 3.11.3 (main, Aug 25 2023, 17:24:38) [GCC 11.4.0]\r\nLinux-5.15.0-91-generic-x86_64-with-glibc2.35\r\n-----\r\nSession information updated at 2024-02-07 10:05\r\n```\r\n\r\n</details>\r\n\n", "before_files": [{"content": "\"\"\"Shared docstrings for preprocessing function parameters.\n\"\"\"\nfrom __future__ import annotations\n\ndoc_adata_basic = \"\"\"\\\nadata\n    Annotated data matrix.\\\n\"\"\"\n\ndoc_expr_reps = \"\"\"\\\nlayer\n    If provided, use `adata.layers[layer]` for expression values instead\n    of `adata.X`.\nuse_raw\n    If True, use `adata.raw.X` for expression values instead of `adata.X`.\\\n\"\"\"\n\ndoc_mask_hvg = \"\"\"\\\nmask\n    To run only on a certain set of genes given by a boolean array\n    or a string referring to an array in :attr:`~anndata.AnnData.var`.\n    By default, uses `.var['highly_variable']` if available, else everything.\nuse_highly_variable\n    Whether to use highly variable genes only, stored in\n    `.var['highly_variable']`.\n    By default uses them if they have been determined beforehand.\n\n    .. deprecated:: 1.10.0\n       Use `mask` instead\n\"\"\"\n\ndoc_obs_qc_args = \"\"\"\\\nqc_vars\n    Keys for boolean columns of `.var` which identify variables you could\n    want to control for (e.g. \"ERCC\" or \"mito\").\npercent_top\n    Which proportions of top genes to cover. If empty or `None` don't\n    calculate. Values are considered 1-indexed, `percent_top=[50]` finds\n    cumulative proportion to the 50th most expressed gene.\\\n\"\"\"\n\ndoc_qc_metric_naming = \"\"\"\\\nexpr_type\n    Name of kind of values in X.\nvar_type\n    The kind of thing the variables are.\\\n\"\"\"\n\ndoc_obs_qc_returns = \"\"\"\\\nObservation level metrics include:\n\n`total_{var_type}_by_{expr_type}`\n    E.g. \"total_genes_by_counts\". Number of genes with positive counts in a cell.\n`total_{expr_type}`\n    E.g. \"total_counts\". Total number of counts for a cell.\n`pct_{expr_type}_in_top_{n}_{var_type}` \u2013 for `n` in `percent_top`\n    E.g. \"pct_counts_in_top_50_genes\". Cumulative percentage of counts\n    for 50 most expressed genes in a cell.\n`total_{expr_type}_{qc_var}` \u2013 for `qc_var` in `qc_vars`\n    E.g. \"total_counts_mito\". Total number of counts for variables in\n    `qc_vars`.\n`pct_{expr_type}_{qc_var}` \u2013 for `qc_var` in `qc_vars`\n    E.g. \"pct_counts_mito\". Proportion of total counts for a cell which\n    are mitochondrial.\\\n\"\"\"\n\ndoc_var_qc_returns = \"\"\"\\\nVariable level metrics include:\n\n`total_{expr_type}`\n    E.g. \"total_counts\". Sum of counts for a gene.\n`n_genes_by_{expr_type}`\n    E.g. \"n_genes_by_counts\". The number of genes with at least 1 count in a cell. Calculated for all cells.\n`mean_{expr_type}`\n    E.g. \"mean_counts\". Mean expression over all cells.\n`n_cells_by_{expr_type}`\n    E.g. \"n_cells_by_counts\". Number of cells this expression is\n    measured in.\n`pct_dropout_by_{expr_type}`\n    E.g. \"pct_dropout_by_counts\". Percentage of cells this feature does\n    not appear in.\\\n\"\"\"\n", "path": "scanpy/preprocessing/_docs.py"}], "after_files": [{"content": "\"\"\"Shared docstrings for preprocessing function parameters.\n\"\"\"\nfrom __future__ import annotations\n\ndoc_adata_basic = \"\"\"\\\nadata\n    Annotated data matrix.\\\n\"\"\"\n\ndoc_expr_reps = \"\"\"\\\nlayer\n    If provided, use `adata.layers[layer]` for expression values instead\n    of `adata.X`.\nuse_raw\n    If True, use `adata.raw.X` for expression values instead of `adata.X`.\\\n\"\"\"\n\ndoc_mask_hvg = \"\"\"\\\nmask\n    To run only on a certain set of genes given by a boolean array\n    or a string referring to an array in :attr:`~anndata.AnnData.var`.\n    By default, uses `.var['highly_variable']` if available, else everything.\nuse_highly_variable\n    Whether to use highly variable genes only, stored in\n    `.var['highly_variable']`.\n    By default uses them if they have been determined beforehand.\n\n    .. deprecated:: 1.10.0\n       Use `mask` instead\n\"\"\"\n\ndoc_obs_qc_args = \"\"\"\\\nqc_vars\n    Keys for boolean columns of `.var` which identify variables you could\n    want to control for (e.g. \"ERCC\" or \"mito\").\npercent_top\n    List of ranks (where genes are ranked by expression) at which the cumulative\n    proportion of expression will be reported as a percentage. This can be used to\n    assess library complexity. Ranks are considered 1-indexed, and if empty or None\n    don't calculate.\n\n    E.g. `percent_top=[50]` finds cumulative proportion to the 50th most expressed gene.\n\"\"\"\n\ndoc_qc_metric_naming = \"\"\"\\\nexpr_type\n    Name of kind of values in X.\nvar_type\n    The kind of thing the variables are.\\\n\"\"\"\n\ndoc_obs_qc_returns = \"\"\"\\\nObservation level metrics include:\n\n`total_{var_type}_by_{expr_type}`\n    E.g. \"total_genes_by_counts\". Number of genes with positive counts in a cell.\n`total_{expr_type}`\n    E.g. \"total_counts\". Total number of counts for a cell.\n`pct_{expr_type}_in_top_{n}_{var_type}` \u2013 for `n` in `percent_top`\n    E.g. \"pct_counts_in_top_50_genes\". Cumulative percentage of counts\n    for 50 most expressed genes in a cell.\n`total_{expr_type}_{qc_var}` \u2013 for `qc_var` in `qc_vars`\n    E.g. \"total_counts_mito\". Total number of counts for variables in\n    `qc_vars`.\n`pct_{expr_type}_{qc_var}` \u2013 for `qc_var` in `qc_vars`\n    E.g. \"pct_counts_mito\". Proportion of total counts for a cell which\n    are mitochondrial.\\\n\"\"\"\n\ndoc_var_qc_returns = \"\"\"\\\nVariable level metrics include:\n\n`total_{expr_type}`\n    E.g. \"total_counts\". Sum of counts for a gene.\n`n_genes_by_{expr_type}`\n    E.g. \"n_genes_by_counts\". The number of genes with at least 1 count in a cell. Calculated for all cells.\n`mean_{expr_type}`\n    E.g. \"mean_counts\". Mean expression over all cells.\n`n_cells_by_{expr_type}`\n    E.g. \"n_cells_by_counts\". Number of cells this expression is\n    measured in.\n`pct_dropout_by_{expr_type}`\n    E.g. \"pct_dropout_by_counts\". Percentage of cells this feature does\n    not appear in.\\\n\"\"\"\n", "path": "scanpy/preprocessing/_docs.py"}]}