From 4385214797dd36ea6459e9adeb5d7cd2324ef980 Mon Sep 17 00:00:00 2001 From: ricardlambea Date: Fri, 24 Mar 2023 16:03:13 +0100 Subject: [PATCH 1/2] Mulliken charge selector --- peleffy/forcefield/calculators.py | 8 ++++++++ peleffy/forcefield/selectors.py | 6 ++++-- peleffy/tests/test_forcefields.py | 10 ++++++++-- peleffy/utils/toolkits.py | 5 +++-- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/peleffy/forcefield/calculators.py b/peleffy/forcefield/calculators.py index fb6bcd60..85d558b9 100644 --- a/peleffy/forcefield/calculators.py +++ b/peleffy/forcefield/calculators.py @@ -92,6 +92,14 @@ class GasteigerCalculator(_PartialChargeCalculator): _name = 'gasteiger' +class MullikenCalculator(_PartialChargeCalculator): + """ + Implementation of the Mulliken partial charge calculator (using + RDKit). + """ + + _name = 'mulliken' + class OPLSChargeCalculator(_PartialChargeCalculator): """ diff --git a/peleffy/forcefield/selectors.py b/peleffy/forcefield/selectors.py index 67636d0b..0688ac12 100644 --- a/peleffy/forcefield/selectors.py +++ b/peleffy/forcefield/selectors.py @@ -92,12 +92,14 @@ class ChargeCalculatorSelector(object): from peleffy.forcefield.calculators import (OPLSChargeCalculator, Am1bccCalculator, GasteigerCalculator, - DummyChargeCalculator) + DummyChargeCalculator, + MullikenCalculator) _AVAILABLE_TYPES = {'opls2005': OPLSChargeCalculator, 'am1bcc': Am1bccCalculator, 'gasteiger': GasteigerCalculator, - 'dummy': DummyChargeCalculator + 'dummy': DummyChargeCalculator, + 'mulliken': MullikenCalculator } def get_by_name(self, charge_method, molecule): diff --git a/peleffy/tests/test_forcefields.py b/peleffy/tests/test_forcefields.py index 63a09ffb..f980aa73 100644 --- a/peleffy/tests/test_forcefields.py +++ b/peleffy/tests/test_forcefields.py @@ -9,7 +9,7 @@ class TestOpenForceField(object): It wraps all tests that check the OpenForceField class. """ - FORCE_FIELD_NAME = 'openff_unconstrained-1.2.1.offxml' + FORCE_FIELD_NAME = 'openff_unconstrained-1.3.0.offxml' # original 1.2.1 def test_name(self): """It checks the name assignment.""" @@ -58,7 +58,7 @@ def test_charge_calculator_selector(self): peleffy.forcefield.calculators.GasteigerCalculator), \ 'Invalid custom selection 1 for the charge calculator' - # Check custom selection 1 + # Check custom selection 2 openff = OpenForceField(self.FORCE_FIELD_NAME) calculator = openff._get_charge_calculator('opls2005', dummy_mol) @@ -67,6 +67,12 @@ def test_charge_calculator_selector(self): peleffy.forcefield.calculators.OPLSChargeCalculator), \ 'Invalid custom selection 2 for the charge calculator' + # Check custom selection 3 + openff = OpenForceField(self.FORCE_FIELD_NAME) + calculator = openff._get_charge_calculator('mulliken', dummy_mol) + assert isinstance(calculator, peleffy.forcefield.calculators.MullikenCalculator), \ + "Invalid custom selection 3 for the charge calculator" + def test_parameterizer(self): """It checks the parameterized method.""" diff --git a/peleffy/utils/toolkits.py b/peleffy/utils/toolkits.py index b4f896f4..e911b512 100644 --- a/peleffy/utils/toolkits.py +++ b/peleffy/utils/toolkits.py @@ -1010,7 +1010,7 @@ def compute_partial_charges(self, molecule, method='am1bcc'): molecule : an peleffy.topology.Molecule The peleffy's Molecule object method : str - The name of the method to use. One of ['gasteiger', 'am1bcc']. + The name of the method to use. One of ['gasteiger', 'am1bcc', 'mulliken']. If None, 'am1bcc' will be used Returns @@ -1027,7 +1027,8 @@ def compute_partial_charges(self, molecule, method='am1bcc'): """ SUPPORTED_CHARGE_METHODS = {'am1bcc': {'antechamber_keyword': 'bcc'}, - 'gasteiger': {'antechamber_keyword': 'gas'} + 'gasteiger': {'antechamber_keyword': 'gas'}, + 'mulliken': {'antechamber_keyword': 'mul'} } if method not in SUPPORTED_CHARGE_METHODS: From c1ebecfebcab23bf8918172c54b6b435c0b17a66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=AD=20Municoy?= Date: Mon, 27 Mar 2023 15:09:20 +0200 Subject: [PATCH 2/2] Fix tests --- peleffy/tests/test_forcefields.py | 2 +- peleffy/tests/test_parameters.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/peleffy/tests/test_forcefields.py b/peleffy/tests/test_forcefields.py index f980aa73..97e6b0f3 100644 --- a/peleffy/tests/test_forcefields.py +++ b/peleffy/tests/test_forcefields.py @@ -9,7 +9,7 @@ class TestOpenForceField(object): It wraps all tests that check the OpenForceField class. """ - FORCE_FIELD_NAME = 'openff_unconstrained-1.3.0.offxml' # original 1.2.1 + FORCE_FIELD_NAME = 'openff_unconstrained-1.2.1.offxml' def test_name(self): """It checks the name assignment.""" diff --git a/peleffy/tests/test_parameters.py b/peleffy/tests/test_parameters.py index 81ddb192..68f0fde6 100644 --- a/peleffy/tests/test_parameters.py +++ b/peleffy/tests/test_parameters.py @@ -922,6 +922,20 @@ def test_gasteiger_method(self): # Check charges check_CHO_charges(parameters) + def test_mulliken_method(self): + """It tests the mulliken method""" + ligand_path = get_data_file_path(self.LIGAND_PATH) + + # Load molecule + molecule = Molecule(ligand_path) + + # Parameterize + ff = OpenForceField(FORCEFIELD_NAME) + parameters = ff.parameterize(molecule, charge_method='mulliken') + + # Check charges + check_CHO_charges(parameters) + def test_OPLS_method(self): """It tests the OPLS method"""