Skip to content

Let the force field resolve the partial charge assignment - #2152

Open
jthorton wants to merge 14 commits into
mainfrom
charge_from_ff
Open

Let the force field resolve the partial charge assignment#2152
jthorton wants to merge 14 commits into
mainfrom
charge_from_ff

Conversation

@jthorton

@jthorton jthorton commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Fixes #2116, #2117

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

  • All new code is appropriately documented (user-facing code must have complete docstrings).
  • Added a news entry, or the changes are not user-facing.
  • Ran pre-commit: you can run pre-commit locally or comment on this PR with pre-commit.ci autofix.
  • Filled in the AI generated code disclosure.

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

@github-actions

Copy link
Copy Markdown

No API break detected ✅

View workflow run

Griffe output
$ griffe check "openfe" -s src --no-inspection --no-color --verbose -a origin/main

$ griffe check "openfecli" -s src --no-inspection --no-color --verbose -a origin/main

Comment thread src/openfe/protocols/openmm_utils/charge_generation.py Outdated
@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.32%. Comparing base (6c88aae) to head (5fbd1ce).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2152      +/-   ##
==========================================
- Coverage   95.04%   90.32%   -4.73%     
==========================================
  Files         206      206              
  Lines       20514    20591      +77     
==========================================
- Hits        19498    18598     -900     
- Misses       1016     1993     +977     
Flag Coverage Δ
fast-tests 90.32% <100.00%> (?)
slow-tests ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@IAlibay IAlibay left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

quick first look

RDKitToolkitWrapper,
)
from openff.units import unit
from sympy.codegen.ast import continue_

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this import necessary?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch not sure why pycharm pulled that in!

@@ -290,6 +291,7 @@ def assign_offmol_partial_charges(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I liked your idea yesterday of having a "forcefield" entry to make it clear that this is the method that was being applied.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added!

Comment thread src/openfe/protocols/openmm_utils/charge_generation.py Outdated
Comment thread src/openfe/protocols/openmm_utils/charge_generation.py Outdated
@jthorton

Copy link
Copy Markdown
Collaborator Author

pre-commit.ci autofix

@jthorton
jthorton requested a review from IAlibay August 20, 2026 08:32

@IAlibay IAlibay left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of things - mainly it doesn't look like the CLI would work right now (maybe it just needs a test to check it).

Comment thread src/openfecli/parameters/plan_network_options.py
Comment thread src/openfe/protocols/openmm_utils/charge_generation.py
forcefields = [forcefields]

# this expects the full file name of the force field offxml file, e.g. "openff-2.0.0.offxml"
# which is different to how settings work which can leave off the .offxml extension

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think now we can use .offxml directly right? Should we change the defaults?

Also what happens if this encounters a non .offxml str? Should we try to add it?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to accept both and added a test, and yes maybe the default should now have the extension as well.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you open a PR on gufe to update the default please?

Comment thread src/openfe/protocols/openmm_utils/charge_generation.py Outdated
# which is different to how settings work which can leave off the .offxml extension
ff = ForceField(*forcefields)
# let the force field resolve the partial charge assignment
charges = ff.get_partial_charges(offmol)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this needs to get wrapped around toolkit_registry_manager, otherwise we'll go back to encountering the annoying rdkit & openeye toolkit aren't compatible problem.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably but which registry would we use as it could influence the charge method used? I think the default is openeye and am1bccelf10 and then fall back to AmberToolsam1bcc?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just use what the user has in the settings for the toolkit_backend and make it clear in the docs that the backend is always followed when a charge is generated.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah this doesn't work if the force field uses nagl charges, as our default is ambertools, we might need to use a different method to make the registry. Maybe something like:
If the user has openeye pass:

  • openeye
  • nagl
  • ambertools
    If the user has rdkit and no openeye:
  • rdkit
  • nagl
  • ambertools

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I don't understand why it's not working.

The "AmberTools" backend is AmberTools + RDKit, that should be enough for NAGL to work no?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok - the issue is that the NAGL registry isn't in there?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be ok to just add the NAGLToolkitWrapper to both AmberTools & OpenEye backend lists - please double check but I think it will still do the "protection" that we're trying to do (i.e. it will block you from doing am1bcc with openeye if you don't want it).

Comment thread src/openfe/tests/protocols/test_openmmutils.py Outdated
@jthorton

Copy link
Copy Markdown
Collaborator Author

pre-commit.ci autofix

@jthorton
jthorton requested a review from IAlibay August 26, 2026 09:11

@IAlibay IAlibay left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good, but yeah we might need to change the backends behaviour. Let me know if you want to have a chat tomorow morning.

off_toolkit_backend: ambertools
number_of_conformers: None
nagl_model: None
forcefields: None

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about including an example of this under the settings help section?

settings = {
"partial_charge": {
"method": "forcefield",
"settings": {"forcefields": ["openff_unconstrained-2.3.0"]},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] Any reason for using unconstrained here? Might be better to use the default we use day-to-day.

forcefields = [forcefields]

# this expects the full file name of the force field offxml file, e.g. "openff-2.0.0.offxml"
# which is different to how settings work which can leave off the .offxml extension

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you open a PR on gufe to update the default please?

if not overwrite:
return offmol

if method.lower() == "forcefield":

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have a check for the other way around too? I'm thinking new users might not easily know you need to set both - especially via the CLI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a "forcefield" optional to assign_partial_charges

2 participants