From eb589a144c239f00264e213dc3cbaae4674e9ee3 Mon Sep 17 00:00:00 2001 From: SaraAngelucci Date: Tue, 12 May 2026 13:38:51 +0200 Subject: [PATCH 1/2] feat: implement ESOL and ClinTox evaluation datasets --- .../eval/contributed_datasets.py | 87 +++++++++++++++++++ tests/test_eval_clintox.py | 16 ++++ tests/test_eval_esol.py | 16 ++++ 3 files changed, 119 insertions(+) create mode 100644 tests/test_eval_clintox.py create mode 100644 tests/test_eval_esol.py diff --git a/src/modernmolbert/eval/contributed_datasets.py b/src/modernmolbert/eval/contributed_datasets.py index 2969c02..8126828 100644 --- a/src/modernmolbert/eval/contributed_datasets.py +++ b/src/modernmolbert/eval/contributed_datasets.py @@ -102,6 +102,67 @@ def load_example_activity_dataset(*, root: str | Path) -> EvalDataset: }, ) +def load_esol(*, root: str | Path) -> EvalDataset: + root = Path(root) + task_names = ["target"] + + train = pd.read_csv(root / "train.csv") + valid_path = root / "valid.csv" + valid = pd.read_csv(valid_path) if valid_path.exists() else None + test = pd.read_csv(root / "test.csv") + + train = _drop_missing_labels(train, task_names=task_names) + test = _drop_missing_labels(test, task_names=task_names) + if valid is not None: + valid = _drop_missing_labels(valid, task_names=task_names) + + return make_eval_dataset_from_splits( + name="esol", + task_type="regression", + task_names=task_names, + train=train, + valid=valid, + test=test, + smiles_column="smiles", + metadata={ + "source": "MoleculeNet ESOL", + "missing_label_policy": "Dropped" + }, + ) + +def load_clintox(*, root: str | Path) -> EvalDataset: + root = Path(root) + task_names = ["FDA_APPROVED"] + + train = pd.read_csv(root / "train.csv") + valid_path = root / "valid.csv" + valid = pd.read_csv(valid_path) if valid_path.exists() else None + test = pd.read_csv(root / "test.csv") + + train = _drop_missing_labels(train, task_names=task_names) + test = _drop_missing_labels(test, task_names=task_names) + if valid is not None: + valid = _drop_missing_labels(valid, task_names=task_names) + + _validate_binary_labels(train, task_name="FDA_APPROVED", split_name="train") + _validate_binary_labels(test, task_name="FDA_APPROVED", split_name="test") + if valid is not None: + _validate_binary_labels(valid, task_name="FDA_APPROVED", split_name="valid") + + return make_eval_dataset_from_splits( + name="clintox", + task_type="classification", + task_names=task_names, + train=train, + valid=valid, + test=test, + smiles_column="smiles", + metadata={ + "source": "MoleculeNet ClinTox", + "missing_label_policy": "Dropped" + }, + ) + def register_contributed_datasets() -> None: """Register project-maintained contributed datasets. @@ -126,4 +187,30 @@ def register_contributed_datasets() -> None: # ) # ) + register_dataset( + DatasetSpec( + name="esol", + task_type="regression", + task_names=("target",), + loader=load_esol, + description="ESOL water solubility regression from MoleculeNet.", + source="https://moleculenet.org/datasets-1", + citation="Wu et al. MoleculeNet: a benchmark for molecular machine learning. Chemical Science (2018).", + license="MIT", + ) + ) + + register_dataset( + DatasetSpec( + name="clintox", + task_type="classification", + task_names=("FDA_APPROVED",), + loader=load_clintox, + description="ClinTox FDA approval classification from MoleculeNet.", + source="https://moleculenet.org/datasets-1", + citation="Wu et al. MoleculeNet: a benchmark for molecular machine learning. Chemical Science (2018).", + license="MIT", + ) + ) + return None diff --git a/tests/test_eval_clintox.py b/tests/test_eval_clintox.py new file mode 100644 index 0000000..3a2f8ba --- /dev/null +++ b/tests/test_eval_clintox.py @@ -0,0 +1,16 @@ +from pathlib import Path +import pandas as pd +from modernmolbert.eval.contributed_datasets import load_clintox + +def test_load_clintox(tmp_path: Path) -> None: + root = tmp_path / "clintox" + root.mkdir() + + pd.DataFrame({"smiles": ["CCO", "CCN", "CCC"], "FDA_APPROVED": [0, 1, None]}).to_csv(root / "train.csv", index=False) + pd.DataFrame({"smiles": ["CCCl", "CCBr"], "FDA_APPROVED": [0, 1]}).to_csv(root / "test.csv", index=False) + + dataset = load_clintox(root=root) + dataset.check() + + assert dataset.name == "clintox" + assert len(dataset.train) == 2 diff --git a/tests/test_eval_esol.py b/tests/test_eval_esol.py new file mode 100644 index 0000000..0ea08fc --- /dev/null +++ b/tests/test_eval_esol.py @@ -0,0 +1,16 @@ +from pathlib import Path +import pandas as pd +from modernmolbert.eval.contributed_datasets import load_esol + +def test_load_esol(tmp_path: Path) -> None: + root = tmp_path / "esol" + root.mkdir() + + pd.DataFrame({"smiles": ["CCO", "CCN", "CCC"], "target": [1.2, -0.5, None]}).to_csv(root / "train.csv", index=False) + pd.DataFrame({"smiles": ["CCCl", "CCBr"], "target": [0.1, 0.2]}).to_csv(root / "test.csv", index=False) + + dataset = load_esol(root=root) + dataset.check() + + assert dataset.name == "esol" + assert len(dataset.train) == 2 From 193a9bfc395cbb2cade44f2b84daae299aaeb7c5 Mon Sep 17 00:00:00 2001 From: SaraAngelucci Date: Wed, 13 May 2026 23:10:20 +0200 Subject: [PATCH 2/2] format contributed files only --- src/modernmolbert/eval/contributed_datasets.py | 12 ++++-------- tests/test_eval_clintox.py | 11 ++++++++--- tests/test_eval_esol.py | 11 ++++++++--- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/modernmolbert/eval/contributed_datasets.py b/src/modernmolbert/eval/contributed_datasets.py index 8126828..b484cd0 100644 --- a/src/modernmolbert/eval/contributed_datasets.py +++ b/src/modernmolbert/eval/contributed_datasets.py @@ -102,6 +102,7 @@ def load_example_activity_dataset(*, root: str | Path) -> EvalDataset: }, ) + def load_esol(*, root: str | Path) -> EvalDataset: root = Path(root) task_names = ["target"] @@ -124,12 +125,10 @@ def load_esol(*, root: str | Path) -> EvalDataset: valid=valid, test=test, smiles_column="smiles", - metadata={ - "source": "MoleculeNet ESOL", - "missing_label_policy": "Dropped" - }, + metadata={"source": "MoleculeNet ESOL", "missing_label_policy": "Dropped"}, ) + def load_clintox(*, root: str | Path) -> EvalDataset: root = Path(root) task_names = ["FDA_APPROVED"] @@ -157,10 +156,7 @@ def load_clintox(*, root: str | Path) -> EvalDataset: valid=valid, test=test, smiles_column="smiles", - metadata={ - "source": "MoleculeNet ClinTox", - "missing_label_policy": "Dropped" - }, + metadata={"source": "MoleculeNet ClinTox", "missing_label_policy": "Dropped"}, ) diff --git a/tests/test_eval_clintox.py b/tests/test_eval_clintox.py index 3a2f8ba..f4d2505 100644 --- a/tests/test_eval_clintox.py +++ b/tests/test_eval_clintox.py @@ -2,15 +2,20 @@ import pandas as pd from modernmolbert.eval.contributed_datasets import load_clintox + def test_load_clintox(tmp_path: Path) -> None: root = tmp_path / "clintox" root.mkdir() - pd.DataFrame({"smiles": ["CCO", "CCN", "CCC"], "FDA_APPROVED": [0, 1, None]}).to_csv(root / "train.csv", index=False) - pd.DataFrame({"smiles": ["CCCl", "CCBr"], "FDA_APPROVED": [0, 1]}).to_csv(root / "test.csv", index=False) + pd.DataFrame({"smiles": ["CCO", "CCN", "CCC"], "FDA_APPROVED": [0, 1, None]}).to_csv( + root / "train.csv", index=False + ) + pd.DataFrame({"smiles": ["CCCl", "CCBr"], "FDA_APPROVED": [0, 1]}).to_csv( + root / "test.csv", index=False + ) dataset = load_clintox(root=root) dataset.check() - + assert dataset.name == "clintox" assert len(dataset.train) == 2 diff --git a/tests/test_eval_esol.py b/tests/test_eval_esol.py index 0ea08fc..15e2f12 100644 --- a/tests/test_eval_esol.py +++ b/tests/test_eval_esol.py @@ -2,15 +2,20 @@ import pandas as pd from modernmolbert.eval.contributed_datasets import load_esol + def test_load_esol(tmp_path: Path) -> None: root = tmp_path / "esol" root.mkdir() - pd.DataFrame({"smiles": ["CCO", "CCN", "CCC"], "target": [1.2, -0.5, None]}).to_csv(root / "train.csv", index=False) - pd.DataFrame({"smiles": ["CCCl", "CCBr"], "target": [0.1, 0.2]}).to_csv(root / "test.csv", index=False) + pd.DataFrame({"smiles": ["CCO", "CCN", "CCC"], "target": [1.2, -0.5, None]}).to_csv( + root / "train.csv", index=False + ) + pd.DataFrame({"smiles": ["CCCl", "CCBr"], "target": [0.1, 0.2]}).to_csv( + root / "test.csv", index=False + ) dataset = load_esol(root=root) dataset.check() - + assert dataset.name == "esol" assert len(dataset.train) == 2