From 9136da0cdcd302f91d8f78744fa2a8df60fb5e58 Mon Sep 17 00:00:00 2001 From: Alyssa Travitz Date: Fri, 15 Nov 2024 13:22:55 -0800 Subject: [PATCH 1/5] adding ugly but working test --- .../test_maximal_network_planner.py | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/konnektor/tests/network_planners/generators/test_maximal_network_planner.py b/src/konnektor/tests/network_planners/generators/test_maximal_network_planner.py index 6e4d215..5dbd8f0 100644 --- a/src/konnektor/tests/network_planners/generators/test_maximal_network_planner.py +++ b/src/konnektor/tests/network_planners/generators/test_maximal_network_planner.py @@ -10,6 +10,33 @@ genScorer, GenAtomMapper, ) +from gufe import LigandAtomMapping, AtomMapper, AtomMapping +from konnektor.utils.toy_data import build_random_dataset + + +class CounterTestMapper(AtomMapper): + def __init__(self): + """ + Build a generic Mapper, that only has use for dummy mappings. + Generates mappings that increment by 1 for testing order-dependent behavior. + """ + pass + + def suggest_mappings(self, molA, molB) -> AtomMapping: + yield LigandAtomMapping(molA, molB, {0:1}) + + @classmethod + def _defaults(cls): + return super()._defaults() + + @classmethod + def _from_dict(cls, d): + s = cls() + [setattr(s, k, v) for k, v in d.items()] + return s + + def _to_dict(self): + return vars(self) @pytest.mark.parametrize("n_process", [1, 2]) @@ -41,3 +68,18 @@ def test_generate_maximal_network( else: for edge in network.edges: assert "score" not in edge.annotations + +def test_generate_maximal_network_missing_scorer(): + """If no scorer is provided, the last mapper tried should be used.""" + + components, empty_mapper, _ = build_random_dataset(n_compounds=2) + counter_mapper = CounterTestMapper() + planner = MaximalNetworkGenerator( + mappers= [empty_mapper, counter_mapper], + scorer=None, + progress=False, + n_processes=1, + ) + network = planner.generate_ligand_network(components) + assert [e for e in network.edges][-1].componentA_to_componentB == {0:1} + [(e.componentA.name, e.componentB.name) for e in network.edges] \ No newline at end of file From 442dbccf80f8c1b01a82e4b9172d23e1f76c5b07 Mon Sep 17 00:00:00 2001 From: Alyssa Travitz Date: Fri, 15 Nov 2024 15:01:01 -0800 Subject: [PATCH 2/5] making test reproducible --- .../test_maximal_network_planner.py | 29 ++++++++++++------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/konnektor/tests/network_planners/generators/test_maximal_network_planner.py b/src/konnektor/tests/network_planners/generators/test_maximal_network_planner.py index 5dbd8f0..3af41d4 100644 --- a/src/konnektor/tests/network_planners/generators/test_maximal_network_planner.py +++ b/src/konnektor/tests/network_planners/generators/test_maximal_network_planner.py @@ -14,16 +14,19 @@ from konnektor.utils.toy_data import build_random_dataset -class CounterTestMapper(AtomMapper): - def __init__(self): +class DummyMapper(AtomMapper): + def __init__(self, id:int): """ Build a generic Mapper, that only has use for dummy mappings. Generates mappings that increment by 1 for testing order-dependent behavior. + + id : use to identify an instance of this class in testing """ - pass + self.id = id def suggest_mappings(self, molA, molB) -> AtomMapping: - yield LigandAtomMapping(molA, molB, {0:1}) + for i in range(3): + yield LigandAtomMapping(molA, molB, {int(self.id):i}) @classmethod def _defaults(cls): @@ -69,17 +72,21 @@ def test_generate_maximal_network( for edge in network.edges: assert "score" not in edge.annotations -def test_generate_maximal_network_missing_scorer(): - """If no scorer is provided, the last mapper tried should be used.""" +def test_generate_maximal_network_missing_scorer(toluene_vs_others): + """If no scorer is provided, the first mapping of the last mapper should be used.""" + + toluene, others = toluene_vs_others + components = others+[toluene] - components, empty_mapper, _ = build_random_dataset(n_compounds=2) - counter_mapper = CounterTestMapper() + id_a = 0 + id_b = 1 planner = MaximalNetworkGenerator( - mappers= [empty_mapper, counter_mapper], + mappers= [DummyMapper(id=id_a), DummyMapper(id=id_b)], scorer=None, progress=False, n_processes=1, ) + network = planner.generate_ligand_network(components) - assert [e for e in network.edges][-1].componentA_to_componentB == {0:1} - [(e.componentA.name, e.componentB.name) for e in network.edges] \ No newline at end of file + + assert [e.componentA_to_componentB for e in network.edges] == len(network.edges)*[{id_b:0}] From b2c76595faed312b53245d9befc2b8e20581f4be Mon Sep 17 00:00:00 2001 From: Alyssa Travitz Date: Fri, 15 Nov 2024 15:24:10 -0800 Subject: [PATCH 3/5] adding heuristic maximal network planner test --- .../test_heuristic_maximal_network_planner.py | 35 +++++++++++-- .../test_maximal_network_planner.py | 49 +++++-------------- 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/konnektor/tests/network_planners/generators/test_heuristic_maximal_network_planner.py b/src/konnektor/tests/network_planners/generators/test_heuristic_maximal_network_planner.py index ab92f91..36bd13a 100644 --- a/src/konnektor/tests/network_planners/generators/test_heuristic_maximal_network_planner.py +++ b/src/konnektor/tests/network_planners/generators/test_heuristic_maximal_network_planner.py @@ -6,12 +6,16 @@ from konnektor.network_analysis import get_is_connected from konnektor.network_planners import HeuristicMaximalNetworkGenerator from konnektor.utils.toy_data import build_random_dataset - +from konnektor.tests.network_planners.conf import ( + genScorer, + GenAtomMapper, + BadMapper, + SuperBadMapper +) @pytest.mark.parametrize("n_process", [1, 2]) @pytest.mark.parametrize("with_progress", [True, False]) -@pytest.mark.parametrize("with_scorer", [True, False]) -def test_generate_maximal_network(with_progress, with_scorer, n_process): +def test_generate_maximal_network(with_progress, n_process): n_compounds = 20 components, genMapper, genScorer = build_random_dataset(n_compounds=n_compounds) @@ -30,3 +34,28 @@ def test_generate_maximal_network(with_progress, with_scorer, n_process): assert len(network.edges) <= edge_count assert len(network.edges) > n_compounds assert get_is_connected(network) + +@pytest.mark.parametrize("n_process", [1, 2]) +@pytest.mark.parametrize("with_progress", [True, False]) +def test_generate_maximal_network_missing_scorer(with_progress, n_process): + n_compounds = 4 + components, _, _ = build_random_dataset(n_compounds=n_compounds) + + planner = HeuristicMaximalNetworkGenerator( + mappers= [SuperBadMapper(), GenAtomMapper(), BadMapper()], + scorer=None, + n_samples=3, + progress=with_progress, + n_processes=n_process, + ) + network = planner.generate_ligand_network(components) + + assert len(network.nodes) == n_compounds + + edge_count = n_compounds * 3 + assert len(network.edges) <= edge_count + assert len(network.edges) > n_compounds + assert get_is_connected(network) + + assert [e.componentA_to_componentB for e in network.edges] == len(network.edges)*[{0:0}] + diff --git a/src/konnektor/tests/network_planners/generators/test_maximal_network_planner.py b/src/konnektor/tests/network_planners/generators/test_maximal_network_planner.py index 3af41d4..07dc4b1 100644 --- a/src/konnektor/tests/network_planners/generators/test_maximal_network_planner.py +++ b/src/konnektor/tests/network_planners/generators/test_maximal_network_planner.py @@ -9,39 +9,12 @@ toluene_vs_others, genScorer, GenAtomMapper, + BadMapper, + SuperBadMapper ) from gufe import LigandAtomMapping, AtomMapper, AtomMapping from konnektor.utils.toy_data import build_random_dataset - -class DummyMapper(AtomMapper): - def __init__(self, id:int): - """ - Build a generic Mapper, that only has use for dummy mappings. - Generates mappings that increment by 1 for testing order-dependent behavior. - - id : use to identify an instance of this class in testing - """ - self.id = id - - def suggest_mappings(self, molA, molB) -> AtomMapping: - for i in range(3): - yield LigandAtomMapping(molA, molB, {int(self.id):i}) - - @classmethod - def _defaults(cls): - return super()._defaults() - - @classmethod - def _from_dict(cls, d): - s = cls() - [setattr(s, k, v) for k, v in d.items()] - return s - - def _to_dict(self): - return vars(self) - - @pytest.mark.parametrize("n_process", [1, 2]) @pytest.mark.parametrize("with_progress", [True, False]) @pytest.mark.parametrize("with_scorer", [True, False]) @@ -72,21 +45,23 @@ def test_generate_maximal_network( for edge in network.edges: assert "score" not in edge.annotations -def test_generate_maximal_network_missing_scorer(toluene_vs_others): - """If no scorer is provided, the first mapping of the last mapper should be used.""" +@pytest.mark.parametrize("n_process", [1, 2]) +@pytest.mark.parametrize("with_progress", [True, False]) +def test_generate_maximal_network_missing_scorer(toluene_vs_others, n_process, with_progress): + """If no scorer is provided, the first mapping of the last mapper should be used. + Note: this test isn't great because BadMapper only returns one mapping + """ toluene, others = toluene_vs_others components = others+[toluene] - id_a = 0 - id_b = 1 planner = MaximalNetworkGenerator( - mappers= [DummyMapper(id=id_a), DummyMapper(id=id_b)], + mappers= [SuperBadMapper(), GenAtomMapper(), BadMapper()], scorer=None, - progress=False, - n_processes=1, + progress=with_progress, + n_processes=n_process, ) network = planner.generate_ligand_network(components) - assert [e.componentA_to_componentB for e in network.edges] == len(network.edges)*[{id_b:0}] + assert [e.componentA_to_componentB for e in network.edges] == len(network.edges)*[{0:0}] From 68d64235e271ba51f1796554964d0f1241ac1d1a Mon Sep 17 00:00:00 2001 From: Alyssa Travitz Date: Mon, 18 Nov 2024 13:33:18 -0800 Subject: [PATCH 4/5] add docstring --- .../generators/test_heuristic_maximal_network_planner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/konnektor/tests/network_planners/generators/test_heuristic_maximal_network_planner.py b/src/konnektor/tests/network_planners/generators/test_heuristic_maximal_network_planner.py index 36bd13a..d70ba78 100644 --- a/src/konnektor/tests/network_planners/generators/test_heuristic_maximal_network_planner.py +++ b/src/konnektor/tests/network_planners/generators/test_heuristic_maximal_network_planner.py @@ -38,6 +38,7 @@ def test_generate_maximal_network(with_progress, n_process): @pytest.mark.parametrize("n_process", [1, 2]) @pytest.mark.parametrize("with_progress", [True, False]) def test_generate_maximal_network_missing_scorer(with_progress, n_process): + """If a scorer isn't provided, the first mapping from the last mapper should be used.""" n_compounds = 4 components, _, _ = build_random_dataset(n_compounds=n_compounds) From 49a7d7ecef56708ce1dcc6aba43757816156d1c3 Mon Sep 17 00:00:00 2001 From: Alyssa Travitz Date: Mon, 18 Nov 2024 13:46:07 -0800 Subject: [PATCH 5/5] updating docstring --- .../generators/test_heuristic_maximal_network_planner.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/konnektor/tests/network_planners/generators/test_heuristic_maximal_network_planner.py b/src/konnektor/tests/network_planners/generators/test_heuristic_maximal_network_planner.py index d70ba78..9802106 100644 --- a/src/konnektor/tests/network_planners/generators/test_heuristic_maximal_network_planner.py +++ b/src/konnektor/tests/network_planners/generators/test_heuristic_maximal_network_planner.py @@ -38,7 +38,9 @@ def test_generate_maximal_network(with_progress, n_process): @pytest.mark.parametrize("n_process", [1, 2]) @pytest.mark.parametrize("with_progress", [True, False]) def test_generate_maximal_network_missing_scorer(with_progress, n_process): - """If a scorer isn't provided, the first mapping from the last mapper should be used.""" + """If no scorer is provided, the first mapping of the last mapper should be used. + Note: this test isn't great because BadMapper only returns one mapping + """ n_compounds = 4 components, _, _ = build_random_dataset(n_compounds=n_compounds)