Skip to content

Commit c823f31

Browse files
committed
fix return_null_data=True to actually return the result dict
Previously return_null_data=True captured null data internally but the return logic only checked return_full_results, so the dict was never surfaced. Now return_null_data=True triggers returning the result dict (lightweight null only), while return_full_results=True includes the full expression matrices.
1 parent 6411dd0 commit c823f31

3 files changed

Lines changed: 45 additions & 24 deletions

File tree

kompot/anndata/differential_expression.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -559,11 +559,12 @@ def de(
559559
)
560560

561561
# ---- 15. Return ----
562+
_return_dict = return_full_results or return_null_data
562563
if copy:
563-
if return_full_results:
564+
if _return_dict:
564565
return result_dict, adata
565566
return adata
566-
if return_full_results:
567+
if _return_dict:
567568
return result_dict
568569
return None
569570

kompot/settings.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -258,11 +258,11 @@ class OutputSettings:
258258
expression matrices, fold changes, and imputations alongside
259259
the lightweight metadata.
260260
return_null_data : bool
261-
Include lightweight null-distribution metadata in the returned
262-
results dict (gene indices, names, seed, Mahalanobis distances)
263-
without the full expression matrices. Ignored when
264-
``return_full_results`` is True (which already includes
265-
everything).
261+
Return the results dict with lightweight null-distribution
262+
metadata (gene indices, names, seed, Mahalanobis distances)
263+
without the full expression matrices. When
264+
``return_full_results`` is also True, the null data
265+
additionally includes the full expression matrices.
266266
compute_mahalanobis : bool
267267
Compute per-gene Mahalanobis distances (DE only).
268268
allow_single_condition_variance : bool

tests/test_return_null_data.py

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -212,21 +212,26 @@ class TestReturnNullDataLightweight:
212212
"""When return_null_data=True (without return_full_results),
213213
result_dict should contain null metadata but NOT expression matrices."""
214214

215-
def test_null_key_present(self):
215+
def test_null_key_present_without_return_full_results(self):
216+
"""return_null_data=True alone should return the result dict."""
216217
adata = _make_adata()
217218
result = kompot.de(
218219
adata, "condition", "A", "B",
219220
gp=kompot.GPSettings(**_FAST_GP),
220221
fdr=FDRSettings(null_genes=10, null_seed=42),
221222
output=OutputSettings(
222-
return_full_results=True,
223+
return_full_results=False,
223224
return_null_data=True,
224225
progress=False,
225226
),
226227
)
228+
assert isinstance(result, dict)
227229
assert "null" in result
230+
assert "table" in result # result dict always has a table
228231

229-
def test_lightweight_has_table_and_metadata(self):
232+
def test_lightweight_no_expression_in_null(self):
233+
"""return_null_data=True without return_full_results should return
234+
the dict but the null entry should NOT have expression matrices."""
230235
adata = _make_adata()
231236
result = kompot.de(
232237
adata, "condition", "A", "B",
@@ -236,23 +241,38 @@ def test_lightweight_has_table_and_metadata(self):
236241
return_full_results=False,
237242
return_null_data=True,
238243
progress=False,
239-
inplace=False,
240244
),
241245
)
242-
# return_null_data alone requires return_full_results to get the dict
243-
# With return_full_results=False and inplace=False, result is None.
244-
# The null data only surfaces through the result_dict, which requires
245-
# return_full_results=True. Let's test with it on.
246-
247-
def test_no_expression_matrices_when_lightweight(self):
248-
"""return_null_data=True without return_full_results should NOT
249-
include the large expression matrices in the null dict."""
246+
null = result["null"]
247+
assert isinstance(null["table"], pd.DataFrame)
248+
assert null["seed"] == 42
249+
for key in (
250+
"condition1_imputed", "condition2_imputed",
251+
"fold_change", "fold_change_zscores",
252+
):
253+
assert key not in null, f"Lightweight mode should not include {key}"
254+
255+
def test_return_null_data_with_copy(self):
256+
"""return_null_data=True with copy=True returns (dict, adata)."""
250257
adata = _make_adata()
251-
# return_null_data=True but return_full_results=False:
252-
# We need return_full_results=True to actually get the dict back,
253-
# so the distinction is: return_null_data alone triggers lightweight,
254-
# return_full_results triggers full. Test the internal _compute_fdr
255-
# directly.
258+
result = kompot.de(
259+
adata, "condition", "A", "B",
260+
gp=kompot.GPSettings(**_FAST_GP),
261+
fdr=FDRSettings(null_genes=10, null_seed=42),
262+
output=OutputSettings(
263+
return_full_results=False,
264+
return_null_data=True,
265+
copy=True,
266+
progress=False,
267+
),
268+
)
269+
assert isinstance(result, tuple)
270+
result_dict, adata_copy = result
271+
assert "null" in result_dict
272+
273+
def test_no_expression_matrices_when_lightweight_internal(self):
274+
"""Test _compute_fdr directly: return_null_data without
275+
return_full_results should not capture expression matrices."""
256276
from kompot.anndata._de_helpers import _compute_fdr
257277

258278
n_real = 10

0 commit comments

Comments
 (0)