Skip to content
This repository has been archived by the owner on May 27, 2024. It is now read-only.

Commit

Permalink
Add more test cases and fix others
Browse files Browse the repository at this point in the history
  • Loading branch information
grst committed Apr 11, 2024
1 parent ef99eb4 commit e59e760
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/multi_condition_comparisions/methods/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ def cond(self, **kwargs) -> np.ndarray:
# We still verify that it's a valid category, otherwise simple typos are not caught and lead to
# zeros in the design matrix.
if var in cond_dict:
# it should never be non-ambiguous. If it happens, it's an edge case we don't know about (-> let it fail)
# Getting the categories should never be non-ambiguous. If it happens, it's an edge case we don't know about (-> let it fail)
tmp_categories = resolve_ambiguous(terms_metadata, "categories")
if (
resolve_ambiguous(terms_metadata, "kind") == Factor.Kind.CATEGORICAL
Expand Down
37 changes: 25 additions & 12 deletions tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,37 +24,50 @@ def _test_single_contrast(self, contrast: Sequence[float], **kwargs) -> DataFram
@pytest.mark.parametrize(
"formula,cond_kwargs,expected_contrast",
[
# single variable
["~ condition", {}, [1, 0]],
["~ condition", {"condition": "A"}, [1, 0]],
["~ condition", {"condition": "B"}, [1, 1]],
["~ condition", {"condition": "42"}, ValueError], # non-existant category
# no-intercept models
["~ 0 + condition", {"condition": "A"}, [1, 0]],
["~ 0 + condition", {"condition": "B"}, [0, 1]],
# Different way of specifying dummy coding
["~ donor", {"donor": "D0"}, [1, 0, 0, 0]],
["~ C(donor)", {"donor": "D0"}, [1, 0, 0, 0]],
["~ C(donor, contr.treatment(base='D2'))", {"donor": "D2"}, [1, 0, 0, 0]],
["~ C(donor, contr.treatment(base='D2'))", {"donor": "D0"}, [1, 1, 0, 0]],
# Handle continuous covariates
["~ donor + continuous", {"donor": "D1"}, [1, 1, 0, 0, 0]],
["~ donor + np.log1p(continuous)", {"donor": "D1"}, [1, 1, 0, 0, 0]],
["~ donor + continuous + np.log1p(continuous)", {"donor": "D0"}, [1, 0, 0, 0, 0, 0]],
# Nonsense models repeating the same variable, which are nonetheless allowed by formulaic
["~ donor + C(donor)", {"donor": "D1"}, [1, 1, 0, 0, 1, 0, 0]],
["~ donor + C(donor, contr.treatment(base='D2'))", {"donor": "D0"}, [1, 0, 0, 0, 1, 0, 0]],
[
"~ donor + continuous + np.log(continuous)",
{"donor": "D0"},
"~ condition + donor + C(donor, contr.treatment(base='D2'))",
{"condition": "A"},
ValueError,
], # current limitation: variables may only be used once per formula
[
"~ donor + C(donor)",
{"donor": "D0"},
ValueError,
], # current limitation: variables may only be used once per formula
], # donor base category can't be resolved because it's ambiguous -> ValueError
# Sum2zero coding
["~ C(donor, contr.sum)", {"donor": "D0"}, [1, 1, 0, 0]],
["~ C(donor, contr.sum)", {"donor": "D3"}, [1, -1, -1, -1]],
# Multiple categorical variables
["~ condition + donor", {"condition": "A"}, [1, 0, 0, 0, 0]],
["~ 0 + condition + donor", {"donor": "D1"}, [0, 0, 1, 0, 0]],
["~ condition + donor", {"donor": "D2"}, [1, 0, 0, 1, 0]],
["~ condition + donor", {"condition": "B", "donor": "D2"}, [1, 1, 0, 1, 0]],
["~ condition * donor", {"condition": "A"}, [1, 0, 0, 0, 0]],
["~ condition + donor + condition:donor", {"condition": "A"}, [1, 0, 0, 0, 0]],
["~ 0 + condition + donor", {"donor": "D1"}, [0, 0, 1, 0, 0]],
# Interaction terms
["~ condition * donor", {"condition": "A"}, [1, 0, 0, 0, 0, 0, 0, 0]],
["~ condition + donor + condition:donor", {"condition": "A"}, [1, 0, 0, 0, 0, 0, 0, 0]],
["~ condition * donor", {"condition": "B", "donor": "D2"}, [1, 1, 0, 1, 0, 0, 1, 0]],
["~ condition * C(donor, contr.treatment(base='D2'))", {"condition": "A"}, [1, 0, 0, 0, 0, 0, 0, 0]],
[
"~ condition * C(donor, contr.treatment(base='D2'))",
{"condition": "B", "donor": "D0"},
[1, 1, 1, 0, 0, 1, 0, 0],
],
["~ condition:donor", {"condition": "A"}, [1, 0, 0, 0, 0]],
# TODO: also include tests for errors that should be caught by .cond
],
)
def test_model_cond(test_adata_minimal, MockLinearModel, formula, cond_kwargs, expected_contrast):
Expand Down

0 comments on commit e59e760

Please sign in to comment.