Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
c5591c8
feat: allow exponentiation post agg for log-fold-change
ilan-gold Apr 7, 2026
7aca4b3
feat: add `illico`
ilan-gold Apr 7, 2026
c2f3738
Merge branch 'main' into ig/exp_post_agg
ilan-gold Apr 7, 2026
c80958a
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold Apr 7, 2026
72318fb
fix: bump numba
ilan-gold Apr 7, 2026
97b4f7c
Merge branch 'ig/illico' of github.com:scverse/scanpy into ig/illico
ilan-gold Apr 7, 2026
b9c8257
chore: probably not either
ilan-gold Apr 7, 2026
5394d2b
chore: now pandas
ilan-gold Apr 7, 2026
8928dfd
fix: anndata
ilan-gold Apr 7, 2026
897a646
fix: just stable then
ilan-gold Apr 7, 2026
af1f523
fix: pin rc
ilan-gold Apr 13, 2026
40d5946
fix: agg name
ilan-gold Apr 13, 2026
74b6d87
fix: only consider scores and pvals
ilan-gold Apr 13, 2026
8352445
chore: p values and z scores only
ilan-gold Apr 13, 2026
1cad431
fix: point an low-vers safe version
ilan-gold Apr 13, 2026
f0d78b4
Merge branch 'main' into ig/exp_post_agg
ilan-gold Apr 13, 2026
d9ad811
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold Apr 13, 2026
c83f82b
fix: make a copy of vectors for writing
ilan-gold Apr 14, 2026
8f201ba
Merge branch 'ig/illico' of github.com:scverse/scanpy into ig/illico
ilan-gold Apr 14, 2026
3ca2957
fix: remove warning filter + `use_rust`
ilan-gold Apr 14, 2026
0bf0976
Merge branch 'main' into ig/exp_post_agg
ilan-gold Apr 14, 2026
a375d31
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold Apr 14, 2026
d0f0db0
chore: add explicit test
ilan-gold Apr 14, 2026
e1c43a1
Merge branch 'ig/exp_post_agg' of github.com:scverse/scanpy into ig/e…
ilan-gold Apr 14, 2026
53a2f74
chore: relnote
ilan-gold Apr 14, 2026
5e2ee5e
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold Apr 15, 2026
fa454d7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 15, 2026
ee037e6
fix: clarify usage of categories
ilan-gold Apr 15, 2026
6557bcf
fix: order
ilan-gold Apr 15, 2026
9299b23
Merge branch 'ig/illico' of github.com:scverse/scanpy into ig/illico
ilan-gold Apr 15, 2026
480a57a
fix: decrease absolute tolerance
ilan-gold Apr 15, 2026
c755a14
fix: `rest` instead of `None`
ilan-gold Apr 16, 2026
ac76f90
fix: respect `groups` arg
ilan-gold Apr 16, 2026
259d8f3
chore: add note
ilan-gold Apr 16, 2026
7373f55
move comment to correct location
flying-sheep Apr 16, 2026
739fffb
add explanation
flying-sheep Apr 16, 2026
db85c7c
typo
flying-sheep Apr 16, 2026
92a2953
fix type
flying-sheep Apr 16, 2026
f66ca68
note
flying-sheep Apr 16, 2026
9a62053
ternary
flying-sheep Apr 16, 2026
9f16597
Merge branch 'main' into ig/exp_post_agg
ilan-gold Apr 16, 2026
0b319b8
fix: LFC unfiorm
ilan-gold Apr 17, 2026
3971219
Merge branch 'main' into ig/exp_post_agg
ilan-gold Apr 17, 2026
585aa87
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold Apr 17, 2026
3dac202
fix; dont make list multiple times
ilan-gold Apr 17, 2026
7fcdac7
Merge branch 'main' into ig/exp_post_agg
flying-sheep Apr 17, 2026
ef5ead2
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold Apr 20, 2026
023aa0f
illico bound
ilan-gold Apr 21, 2026
9fe02a3
fix: re-disallow direct references
ilan-gold Apr 21, 2026
6aca9ca
chore: `mean_in_log_space` instead of `exp_post_agg`
ilan-gold Apr 22, 2026
0437475
Merge branch 'main' into ig/exp_post_agg
ilan-gold Apr 22, 2026
d15aede
docs: use upstream APIs (#4083)
flying-sheep Apr 23, 2026
d6f2c51
perf: Combat perf improvements (#4070)
ilaykav Apr 24, 2026
44cfc6e
docs: clarify method vs transformer in sc.pp.neighbors (#4079)
CuiweiG Apr 24, 2026
b448347
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold Apr 24, 2026
2b60935
fix: limit Numba threads in Wilcoxon path of rank_genes_groups (#4082)
JhonatanFelix Apr 24, 2026
3f902dd
Merge branch 'main' into ig/exp_post_agg
ilan-gold Apr 24, 2026
2467433
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold Apr 24, 2026
d1aa5fb
Merge branch 'main' into ig/exp_post_agg
ilan-gold Apr 27, 2026
2585d2c
Update pyproject.toml
ilan-gold Apr 27, 2026
6a1f917
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold Apr 27, 2026
152c344
Merge branch 'main' into ig/exp_post_agg
ilan-gold Apr 27, 2026
c24ebd0
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold Apr 27, 2026
e13cb6a
fix: mean_in_log_space pass through
ilan-gold Apr 28, 2026
62e6c87
fix: no defaults internall on `_compute_statistics`
ilan-gold Apr 28, 2026
bd5f675
Merge branch 'main' into ig/exp_post_agg
ilan-gold Apr 28, 2026
a9d9f0a
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold Apr 28, 2026
aac3189
Merge branch 'main' into ig/exp_post_agg
ilan-gold May 4, 2026
487be58
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold May 4, 2026
977e254
Zb/illico fixes (#4102)
zboldyga May 11, 2026
36c5039
Merge branch 'main' into ig/exp_post_agg
ilan-gold May 16, 2026
36acd5b
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold May 18, 2026
9678e40
Merge branch 'main' into ig/exp_post_agg
ilan-gold Jun 8, 2026
168de8b
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold Jun 16, 2026
c1f0fbc
Merge branch 'main' into ig/exp_post_agg
ilan-gold Jun 16, 2026
5cc6647
Merge branch 'ig/exp_post_agg' into ig/illico
ilan-gold Jun 16, 2026
7ab15f9
feat: use `groups` argument
ilan-gold Jun 16, 2026
3d19c95
Merge branch 'main' into ig/illico
ilan-gold Jun 16, 2026
2363ee7
chore: p-value alteration
ilan-gold Jun 22, 2026
b522c71
Update tests/test_rank_genes_groups.py
ilan-gold Jun 29, 2026
dbbe64d
fix: address comments
ilan-gold Jun 29, 2026
4216aad
Merge branch 'main' into ig/illico
ilan-gold Jun 29, 2026
98e3d71
test
ilan-gold Jun 30, 2026
264c683
Merge branch 'ig/illico' of github.com:scverse/scanpy into ig/illico
ilan-gold Jun 30, 2026
c99dd41
Merge branch 'main' into ig/illico
ilan-gold Jun 30, 2026
0c33493
Merge branch 'main' into ig/illico
ilan-gold Jul 1, 2026
59b9119
Merge branch 'main' into ig/illico
ilan-gold Jul 2, 2026
192d3ea
Merge branch 'main' into ig/illico
ilan-gold Jul 2, 2026
4479fc0
feat: illico as default v2
ilan-gold Jul 2, 2026
1492048
fix: no illico 0.6.0
ilan-gold Jul 2, 2026
e808e69
pin illico
ilan-gold Jul 3, 2026
ef18687
chore: relnote
ilan-gold Jul 3, 2026
a623d40
Merge branch 'main' into ig/illico
ilan-gold Jul 3, 2026
0940df2
intersphinx
ilan-gold Jul 3, 2026
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: 1 addition & 0 deletions docs/release-notes/3653.feat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add {attr}`scanpy.settings.preset` setting with the new preset {attr}`~scanpy.Preset.ScanpyV2Preview` {smaller}`P Angerer`
1 change: 0 additions & 1 deletion docs/release-notes/3653.feature.md

This file was deleted.

3 changes: 3 additions & 0 deletions docs/release-notes/4038.feat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Introduce blazing-fast [`illico`][] as a new `wilcoxon` `method` in {func}`~scanpy.tl.rank_genes_groups`. Use it via either `method="wilcoxon_illico"` or via {attr}`~scanpy.Preset.ScanpyV2Preview` {smaller}`I Gold`

[`illico`]: https://github.com/remydubois/illico
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ scanorama = [ "scanorama" ]
scrublet = [ "scikit-image>=0.25" ]
# highly_variable_genes method 'seurat_v3'
skmisc = [ "scikit-misc>=0.5.1" ]
scanpy2 = [ "igraph>=0.10.8", "scikit-misc>=0.5.1" ]
illico = [ "illico @ git+https://github.com/ilan-gold/illico@ig/dask_optional" ]
scanpy2 = [ "igraph>=0.10.8", "scanpy[illico]", "scikit-misc>=0.5.1" ]

[dependency-groups]
dev = [
Expand All @@ -108,6 +109,7 @@ dev = [
test = [
"scanpy[dask-ml]",
"scanpy[dask]",
"scanpy[illico]",
"scanpy[leiden]",
"scanpy[plotting]",
"scanpy[scrublet]",
Expand Down Expand Up @@ -152,6 +154,7 @@ test-min = [
[tool.hatch]
version.source = "vcs"
version.raw-options.version_scheme = "release-branch-semver"
metadata.allow-direct-references = true
build.targets.wheel.packages = [ "src/scanpy", "src/testing" ]

[tool.ruff]
Expand Down
4 changes: 3 additions & 1 deletion src/scanpy/_settings/presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
]


type DETest = Literal["logreg", "t-test", "wilcoxon", "t-test_overestim_var"]
type DETest = Literal[
"logreg", "t-test", "wilcoxon", "wilcoxon_illico", "t-test_overestim_var"
]
type HVGFlavor = Literal["seurat", "cell_ranger", "seurat_v3", "seurat_v3_paper"]
type LeidenFlavor = Literal["leidenalg", "igraph"]

Expand Down
79 changes: 74 additions & 5 deletions src/scanpy/tools/_rank_genes_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
import numba
import numpy as np
import pandas as pd
from anndata import AnnData
from fast_array_utils.numba import njit
from fast_array_utils.stats import mean_var
from scipy import sparse

from .. import _utils
from .. import logging as logg
from .._compat import CSBase
from .._settings import Default
from .._settings import Default, Preset
from .._settings.presets import DETest
from .._utils import (
_numba_thread_limit,
Expand All @@ -28,7 +29,6 @@
from collections.abc import Generator, Iterable
from typing import Literal

from anndata import AnnData
from numpy.typing import NDArray


Expand All @@ -47,6 +47,35 @@ def _select_top_n(scores: NDArray, n_top: int):
return global_indices


def _illico_results_to_iter(
illico_df: pd.DataFrame,
groups_order: NDArray,
ireference: int | None,
*,
copy_pvalues: bool,
) -> Generator[tuple[int, NDArray[np.floating], NDArray[np.floating]]]:
"""Yield per-group ``(index, z, p)`` tuples from illico's long-form output.

illico returns a DataFrame with a 2-level MultiIndex ``(pert, feature)``
and columns including ``z_score`` and ``p_value``. We stream one group
at a time via `pandas.Series.loc`, trusting illico_df groups are ordered
by ``var_name``.
"""
ref_label = None if ireference is None else groups_order[ireference]
z_series = illico_df["z_score"]
p_series = illico_df["p_value"]
illico_groups = set(illico_df.index.unique(level="pert"))
return (
(
group_index,
z_series.loc[group_name].to_numpy(),
p_series.loc[group_name].to_numpy(copy=copy_pvalues),
)
for group_index, group_name in enumerate(groups_order)
if group_name != ref_label and group_name in illico_groups
)


@njit
def rankdata(data: NDArray[np.number]) -> NDArray[np.float64]:
"""Parallelized version of scipy.stats.rankdata."""
Expand Down Expand Up @@ -141,6 +170,7 @@ def __init__(
self.expm1_func = lambda x: np.expm1(x * np.log(base))
else:
self.expm1_func = np.expm1
self.group_col = adata.obs[groupby].array

self.groups_order, self.groups_masks_obs = _utils.select_groups(
adata, groups, groupby
Expand Down Expand Up @@ -424,6 +454,40 @@ def logreg(
if len(self.groups_order) <= 2:
break

def illico(
self, *, tie_correct: bool, corr_method: _CorrMethod
) -> Generator[tuple[int, NDArray[np.floating], NDArray[np.floating]], None, None]:
from illico import asymptotic_wilcoxon

illico_df = asymptotic_wilcoxon(
AnnData(
X=self.X,
var=pd.DataFrame(index=self.var_names),
obs=pd.DataFrame(
index=pd.RangeIndex(self.X.shape[0]).astype("str"),
data={"group": self.group_col},
),
),
reference=self.groups_order[self.ireference]
if self.ireference is not None
else None,
group_keys="group",
return_as_scanpy=False,
is_log1p=True,
tie_correct=tie_correct,
use_continuity=False,
alternative="two-sided",
use_rust=False,
groups=self.groups_order,
)
return _illico_results_to_iter(
illico_df,
self.groups_order,
self.ireference,
# p-values are altered by this correction method
copy_pvalues=corr_method == "benjamini-hochberg",
)

def compute_statistics( # noqa: PLR0912
self,
method: DETest,
Expand All @@ -441,8 +505,12 @@ def compute_statistics( # noqa: PLR0912
if not mean_in_log_space:
# If we are not exponentiating after the mean aggregation, we need to recalculate the stats.
self._basic_stats(exponentiate_values=True)
elif method == "wilcoxon":
generate_test_results = self.wilcoxon(tie_correct=tie_correct)
elif "wilcoxon" in method:
generate_test_results = (
self.illico(tie_correct=tie_correct, corr_method=corr_method)
if "illico" in method
else self.wilcoxon(tie_correct=tie_correct)
)
# If we're not exponentiating after the mean aggregation, then do it now.
self._basic_stats(exponentiate_values=not mean_in_log_space)
elif method == "logreg":
Expand All @@ -451,7 +519,6 @@ def compute_statistics( # noqa: PLR0912
self.stats = None

n_genes = self.X.shape[1]

for group_index, scores, pvals in generate_test_results:
group_name = str(self.groups_order[group_index])

Expand Down Expand Up @@ -651,6 +718,8 @@ def rank_genes_groups( # noqa: PLR0912, PLR0913, PLR0915
mean_in_log_space = settings.preset.rank_genes_groups.mean_in_log_space
if method is None or isinstance(method, Default):
method = settings.preset.rank_genes_groups.method
if settings.preset is Preset.ScanpyV2Preview:
method = "wilcoxon_illico"
Comment on lines 720 to +722

@flying-sheep flying-sheep Jul 3, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the tone of this comment, I’m not intending it to be as sassy as it reads lol


that makes no sense.

This configuration exists exactly for line 720 do do what you’re now doing in the two lines after.

Preset.ScanpyV2Preview: RankGenesGroupsPreset(
method="wilcoxon", mask_var=None, mean_in_log_space=False
),

So that configuration is now a lie and ignored because you hardcode the default here instead, why?

Re-requesting your review here

if you press the button, I’ll actually see that!

image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies, just forgot to push the button after the comment :)

My thinking goes that I do not want people using wilcoxon_illico parameter and therefore don’t want it hardcoded as the scanpy 2.0 default in the preset.

I would start a deprecation cycle for wilcoxon_illico once 2.0 gets closer.

But I think this might just be too complicated and not worth the slightly-cleaner preset appearance.

We could just make the preset itself wilcoxon_illico and then deprecate people passing in willcoxon_illico manually, instead pointing the preset.

Sorry for the confusion :/ This was sort of a bad middle ground between having wilcoxon_illico with no plan for it, and not having it at all, instead relying purely on the preset.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof, I must have failed to read half of your comment above, sorry! I get it now!

But wouldn’t it be easier to just not have "wilcoxon_ilico" at all then? Just check for if method == "wilcoxon" and settings.preset == Preset.ScanpyV2Preview?


mask_var = _check_mask(adata, mask_var, "var")

Expand Down
1 change: 1 addition & 0 deletions src/testing/scanpy/_pytest/marks.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def _generate_next_value_(
skimage = "scikit-image"
skmisc = "scikit-misc"
zarr = auto()
illico = auto()
# external
bbknn = auto()
harmony = "harmonyTS"
Expand Down
143 changes: 139 additions & 4 deletions tests/test_rank_genes_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
from scanpy._utils.random import _LegacyRng
from scanpy.get import rank_genes_groups_df
from scanpy.tools import rank_genes_groups
from scanpy.tools._rank_genes_groups import _RankGenes
from scanpy.tools._rank_genes_groups import _illico_results_to_iter, _RankGenes
from testing.scanpy._helpers import random_mask
from testing.scanpy._helpers.data import pbmc68k_reduced
from testing.scanpy._pytest.marks import needs
from testing.scanpy._pytest.params import ARRAY_TYPES, ARRAY_TYPES_MEM

if TYPE_CHECKING:
from collections.abc import Callable
from collections.abc import Callable, Sequence
from typing import Any, Literal

from numpy.lib.npyio import NpzFile
Expand Down Expand Up @@ -78,6 +79,25 @@ def get_true_scores(method: Literal["t-test", "wilcoxon"]) -> Expected:
return Expected(names=expected["names"].astype("T"), scores=expected["scores"])


def get_illico_results_df(
n_groups: int, n_genes: int, *, seed: int = 0
) -> pd.DataFrame:
"""Synthetic illico-shaped output used by the _illico_results_to_iter tests.

Features are in deliberately non-ascending to test ``var_name`` ordering.
"""
rng = np.random.default_rng(seed)
groups = [f"g{i}" for i in range(n_groups)]
features = [f"f{n_genes - 1 - j}" for j in range(n_genes)] # reversed -> not sorted
return pd.DataFrame(
{
"z_score": rng.normal(size=n_groups * n_genes),
"p_value": rng.uniform(size=n_groups * n_genes),
},
index=pd.MultiIndex.from_product([groups, features], names=["pert", "feature"]),
)


# TODO: Make dask compatible
@pytest.mark.parametrize("method", ["t-test", "wilcoxon"])
@pytest.mark.parametrize("array_type", ARRAY_TYPES_MEM)
Expand Down Expand Up @@ -352,6 +372,113 @@ def test_mask_not_equal():
assert not np.array_equal(no_mask, with_mask)


@pytest.mark.parametrize(
("groups_order", "ireference", "expected_indices"),
[
(["g0", "g1", "g2"], None, [0, 1, 2]),
(["g0", "g1", "g2"], 1, [0, 2]),
],
ids=["vs_rest", "vs_reference"],
)
@pytest.mark.parametrize("corr_method", ["benjamini-hochberg", "bonferroni"])
def test_illico_iter(
groups_order: list[str],
ireference: int | None,
expected_indices: list[int],
corr_method: Literal["benjamini-hochberg", "bonferroni"],
):
df = get_illico_results_df(n_groups=3, n_genes=4)
feature_order = df.index.unique(level="feature")
out = list(
_illico_results_to_iter(
df,
np.array(groups_order),
ireference,
copy_pvalues=corr_method == "benjamini-hochberg",
)
)
assert sorted(t[0] for t in out) == sorted(expected_indices)
for gi, z, p in out:
sub = df.xs(groups_order[gi], level=0).reindex(feature_order)
np.testing.assert_array_equal(z, sub["z_score"].to_numpy())
np.testing.assert_array_equal(p, sub["p_value"].to_numpy())


@pytest.mark.parametrize("corr_method", ["benjamini-hochberg", "bonferroni"])
@pytest.mark.parametrize("test", ["ovo", "ovr"]) # pairwise or vs. rest
@pytest.mark.parametrize(
"mean_in_log_space", [True, False], ids=["log_space_mean", "linear_space_mean"]
)
@pytest.mark.parametrize(
"tie_correct", [True, False], ids=["tie_correct", "no_tie_correct"]
)
@pytest.mark.parametrize("groups", [["CD14+ Monocyte", "Dendritic"], "all"])
@pytest.mark.filterwarnings("ignore:invalid value encountered:RuntimeWarning")
@needs.illico
def test_illico(
test: Literal["ovo", "ovr"],
corr_method: Literal["benjamini-hochberg", "bonferroni"],
subtests: pytest.Subtests,
groups: Literal["all"] | Sequence[str],
*,
mean_in_log_space: bool,
tie_correct: bool,
):

pbmc = pbmc68k_reduced()
pbmc.raw.X.sum_duplicates()
pbmc.raw.X.sort_indices()
pbmc_illico = pbmc.copy()

reference = pbmc.obs["bulk_labels"].iloc[0] if test == "ovo" else "rest"
sc.tl.rank_genes_groups(
pbmc_illico,
groupby="bulk_labels",
method="wilcoxon_illico",
reference=reference if test == "ovo" else "rest",
n_genes=pbmc.n_vars,
tie_correct=tie_correct,
corr_method=corr_method,
mean_in_log_space=mean_in_log_space,
groups=groups,
)

sc.tl.rank_genes_groups(
pbmc,
groupby="bulk_labels",
method="wilcoxon",
reference=reference if test == "ovo" else "rest",
n_genes=pbmc.n_vars,
tie_correct=tie_correct,
corr_method=corr_method,
mean_in_log_space=mean_in_log_space,
groups=groups,
)
scanpy_results = pbmc.uns["rank_genes_groups"]
illico_results = pbmc_illico.uns["rank_genes_groups"]
assert set(illico_results.keys()) == set(scanpy_results.keys()), (
"Output keys do not match Scanpy's output format."
)

for k, ref in scanpy_results.items():
with subtests.test(k):
if k in ["params", "names"]:
# We can skip names ordering check as if incorrect, other values will mismatch
continue
res = np.array(illico_results[k].tolist())
ref_arr = np.array(ref.tolist())
mask = np.isfinite(ref_arr) * np.isfinite(
res
) # Mask to ignore inf values in the comparison
np.testing.assert_allclose(
ref_arr[mask],
res[mask],
rtol=0,
atol=1e-6,
err_msg=f"Mismatch in '{k}' values between asymptotic_wilcoxon and Scanpy outputs.",
)


@pytest.mark.parametrize(
("mean_in_log_space", "expected_logfc"),
[
Expand All @@ -363,10 +490,18 @@ def test_mask_not_equal():
(False, -1.0),
],
)
@pytest.mark.parametrize("method", ["wilcoxon", "t-test", "t-test_overestim_var"])
@pytest.mark.parametrize(
"method",
[
"wilcoxon",
"t-test",
"t-test_overestim_var",
pytest.param("wilcoxon_illico", marks=needs.illico),
],
)
def test_mean_in_log_space(
expected_logfc: float,
method: Literal["wilcoxon", "t-test", "t-test_overestim_var"],
method: Literal["wilcoxon", "wilcoxon_illico", "t-test", "t-test_overestim_var"],
*,
mean_in_log_space: bool,
):
Expand Down
Loading