Non-deterministic charge validation - #2132
Conversation
|
pre-commit.ci autofix |
for more information, see https://pre-commit.ci
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2132 +/- ##
==========================================
- Coverage 95.20% 90.50% -4.70%
==========================================
Files 213 213
Lines 21138 21146 +8
==========================================
- Hits 20124 19139 -985
- Misses 1014 2007 +993
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| def benzene_charged_system(self, benzene_modifications): | ||
| return ChemicalSystem({"ligand": benzene_modifications["benzene"]}, name="charged") | ||
|
|
||
| @pytest.fixture |
There was a problem hiding this comment.
Would it make sense to also add a test where the first smc is charged and the second does not have charges? How would we want to handle such a case?
There was a problem hiding this comment.
Added a test with a system with a mix of charged and uncharged SMCs, this will raise an error on the first one that fails validation. Do you think it would be better however to list all of the SMCs which fail to avoid playing wack-a-mole?
There was a problem hiding this comment.
Changed to flag all components in the ChemicalSystem which fail validation in one error message to hopefully make the experience better!
|
|
||
| for smc in smcs: | ||
| offmol = smc.to_openff() | ||
| if offmol.partial_charges is not None and np.any(offmol.partial_charges): |
There was a problem hiding this comment.
Would we want to support a case where the user supplies partial charges will all zeros?
There was a problem hiding this comment.
+1 - given we have our own benchmark case where we want to do this, we probably should support it
There was a problem hiding this comment.
Yes good idea. Currently, this only works as a Library charge would we want to keep that as a source of protection to make sure users know what they are doing or allow it as charges on the molecule as well?
There was a problem hiding this comment.
That's a good point - I think if it's easily allowed by LibraryCharge then it might be better to keep the check in. There's too many ways someone could accidentally add partial charges.
IAlibay
left a comment
There was a problem hiding this comment.
I think this matches what we discussed yesterday - as you mentioned, we should be able to drop the partial charge assignment calls in Protocols with this.
|
|
||
| for smc in smcs: | ||
| offmol = smc.to_openff() | ||
| if offmol.partial_charges is not None and np.any(offmol.partial_charges): |
There was a problem hiding this comment.
+1 - given we have our own benchmark case where we want to do this, we probably should support it
# Conflicts: # src/openfe/tests/protocols/test_openmmutils.py
|
pre-commit.ci autofix |
|
pre-commit.ci autofix |
for more information, see https://pre-commit.ci
|
🚨 API breaking changes detected! 🚨 Griffe output |
|
pre-commit.ci autofix |
|
pre-commit.ci autofix |
for more information, see https://pre-commit.ci
|
|
||
| @pytest.mark.parametrize("num", [i for i in range(1, 30)]) | ||
| def test_plot_2D_rmsd(num): | ||
| def test_plot_2D_rmsd(): |
There was a problem hiding this comment.
Sneaking this in can remove if wanted, though, locally this goes from 8s to 650ms while testing more aspects of the output.
There was a problem hiding this comment.
Please move it to a separate PR.
|
pre-commit.ci autofix |
for more information, see https://pre-commit.ci
| @@ -27,7 +27,7 @@ def test_get_molecule_sdf(): | |||
|
|
|||
|
|
|||
| def test_get_molecule_mol2(): | |||
There was a problem hiding this comment.
Should we allow loading from mol2? If we go via rdkit -> SMC we silently drop the charges which the users might have intended to use?
There was a problem hiding this comment.
For now yes, we should retain mol2 as an option - this is because it's something we used to offer and we shouldn't break the API over it.
There was a problem hiding this comment.
If we're worried about dropping charges, then the best option for now would be to validate & warn at SMC creation.
There was a problem hiding this comment.
Yeah I think we need to either keep them or warn as they also silently get replaced with am1bcc currently, gufe issue OpenFreeEnergy/gufe#828
There was a problem hiding this comment.
Are we moving these to mol2 because we want to use them elsewhere?
There was a problem hiding this comment.
I have changed them over to SDF as the charges are getting dropped when reading from mol2, triggering the new validation error in tests, the other option is to update gufe to pull these charges when building from rdkit?
|
|
||
| @pytest.mark.parametrize("num", [i for i in range(1, 30)]) | ||
| def test_plot_2D_rmsd(num): | ||
| def test_plot_2D_rmsd(): |
There was a problem hiding this comment.
Please move it to a separate PR.
|
|
||
| # We count library and nagl charges as deterministic | ||
| # While users could use a deterministic charge method with increments we don't currently support this | ||
| if not labels["LibraryCharges"] and "NAGLCharges" not in labels: |
There was a problem hiding this comment.
Is LibraryCharges always guaranteed as a key or could it KeyError?
There was a problem hiding this comment.
Good catch it could be missing, added support for it and a test.
| settings = self._get_settings() | ||
|
|
||
| # Assign partial charges now to avoid any discrepancies later | ||
| self._assign_partial_charges(settings["charge_settings"], small_mols) |
There was a problem hiding this comment.
I've been thinking more about this one - we're silently removing this, but won't users get caught out if they do use a deterministic charge method in the partial charge settings, e.g. NAGL?
There was a problem hiding this comment.
Yeah that would be the downside, users would have to either use a ff with a NAGL handler or pre-charge them. If we keep support for NAGL and espaloma charge methods at runtime only that could work with the default setting being forcefield. It could be confusing if users have to define the forcefield to use in two places 1) the charges setting object and 2) small molecule force field, and then what happens if these are different?
Ideally I would love to keep this as simple as possible for users, we already encourage charging before running so moving to openfe will do no runtime charge generation doesn't feel like too much of a change?
| def test_dry_run_charge_backends( | ||
| CN_molecule, tmp_path, method, backend, ref_key, protocol_dry_settings, am1bcc_ref_charges | ||
| ): | ||
| def test_dry_run_missing_charges(CN_molecule, protocol_dry_settings): |
There was a problem hiding this comment.
It would be good to have a dry run where we use nagl charges
There was a problem hiding this comment.
This would also raise the error, or do you mean with a forcefield with a NAGL handler?
| BENZ = """\ | ||
| benzene | ||
| PyMOL2.5 3D 0 | ||
| RDKit 3D |
There was a problem hiding this comment.
Ah this is me passing them through openff to get charges for them, they were being assigned during a test which now triggers the validation error, I can just add the partial charge tag and undo the other changes?
| @@ -27,7 +27,7 @@ def test_get_molecule_sdf(): | |||
|
|
|||
|
|
|||
| def test_get_molecule_mol2(): | |||
There was a problem hiding this comment.
For now yes, we should retain mol2 as an option - this is because it's something we used to offer and we shouldn't break the API over it.
| @@ -27,7 +27,7 @@ def test_get_molecule_sdf(): | |||
|
|
|||
|
|
|||
| def test_get_molecule_mol2(): | |||
There was a problem hiding this comment.
If we're worried about dropping charges, then the best option for now would be to validate & warn at SMC creation.
Fixes #2115 by adding a validation method that attempts to catch partial charge generation methods which are used at runtime and are nondeterministic.
LLM / AI generated code disclosure
LLMs or other AI-powered tools (beyond simple IDE use cases) were used in this contribution: yes / no
If yes, please provide details here: No
Checklist
newsentry, or the changes are not user-facing.pre-commit.ci autofix.Manual Tests: these are slow so don't need to be run every commit, only before merging and when relevant changes are made (generally at reviewer-discretion).
Developers certificate of origin