-
Notifications
You must be signed in to change notification settings - Fork 75
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Move atomtyping step into a specific function #159
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! Could you also add the check to make sure that every atom has atomtypes into this PR?
foyer/forcefield.py
Outdated
@@ -308,6 +308,8 @@ def apply(self, topology, references_file=None, *args, **kwargs): | |||
references_file : str, optional, default=None | |||
Name of file where force field references will be written (in Bibtex | |||
format) | |||
use_residue_map : boolean | |||
Bypass atomtyping duplicate residues using a residue map |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you maybe clarify a bit more what this does via the variable name and/or the description here? Maybe something along the lines of copy_atomtypes_to_duplicate_residues
Do you want this in a test or also in the function itself? |
The function itself. We cannot build a system if there are missing atomtypes. |
I don't think the docstring I added is great (please suggest fixes/improvements!) but it's more descriptive. Personally I like the name of the argument - it's not great that it describes a variable that's totally internal - |
And coveralls is whining that I added one un-tested line but only three tested lines 🙄 |
Doc string LGTM! Would be easy to add a test case that triggers the error to get that coverage up 😁 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good! Just a few comments.
foyer/forcefield.py
Outdated
@@ -308,6 +308,15 @@ def apply(self, topology, references_file=None, *args, **kwargs): | |||
references_file : str, optional, default=None | |||
Name of file where force field references will be written (in Bibtex | |||
format) | |||
use_residue_map : boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple nitpicks in this docstring. Could you make this use_residue_map : boolean, optional, default=True
?
foyer/forcefield.py
Outdated
Store atomtyped topologies of residues to a dictionary that maps | ||
them to residue names. Each topology, including atomtypes, will be | ||
copied to other residues with the same name. This avoids repeatedly | ||
calling the subgraph isomorphism on idential residues and should |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo (should be identical
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should probably have a vim plugin that prevents me from making these sorts of mistakes....
foyer/forcefield.py
Outdated
them to residue names. Each topology, including atomtypes, will be | ||
copied to other residues with the same name. This avoids repeatedly | ||
calling the subgraph isomorphism on idential residues and should | ||
result in better performance for systems with many identital |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo (should be identical
)
@@ -317,6 +326,7 @@ def apply(self, topology, references_file=None, *args, **kwargs): | |||
positions = np.empty(shape=(topology.getNumAtoms(), 3)) | |||
positions[:] = np.nan | |||
box_vectors = topology.getPeriodicBoxVectors() | |||
topology = self.run_atomtyping(topology, use_residue_map=use_residue_map) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
foyer/forcefield.py
Outdated
---------- | ||
topology : openmm.app.Topology | ||
Molecular structure to find atom types of | ||
use_residue_map : boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto the comments on the above docstring
foyer/forcefield.py
Outdated
raise ValueError('Not all atoms in topology have atom types') | ||
|
||
return topology | ||
|
||
def createSystem(self, topology, atomtype=True, use_residue_map=True, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double check me but I think the base method includes the logic for template based atomtyping
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll clean up the arguments but this and a few other ideas with Forcefield.createSystem
vs OpenMM's original function should be dealt with at some point. There's an open issue about templating or something that I can't find at the moment but should be referenced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We think you're right in saying that they do their reside teamplate-based atomtyping in their Forcefield.createSystem
. It doesn't appear we can use their base method out of the box.
Worth noting that their while templates are much more involved, we are already doing some work in creating a map between residue/molecule names to atomtyped topologies but trashing it once the system is atomtyped. I don't know if it's feasible or worth considering trying to save residue_map
to disk? Or maybe converting it into a single large residueTemplate
that could then be passed to OpenMM's base method?
Here's their method at a point in history that should be close to when we grabbed it:
Also notable that there have been some updates to that block of in the past year. Probably not much of consequence now but something to worry about later, especially if we want great integration with OpenMM ...
I'm having trouble seeing a good way to test for missing atomtypes. If an atom in the topology truly lacks atomtypes defined in the forcefield, I think errors in |
In this case I just don't know how to raise that error. I get how to use |
I would just call createSystem without the atomtyping flag and it should yell at you |
But that argument is gone now (the atomtyping happens before We can try applying an inappropriate force field to a molecule,
|
Ok good point - sorry I misread how you had implemented this. I think we're good then since we already guarantee that all atoms got a type before calling |
One of the travis builds on mac got hung up on something, but the second most recent test did not, and the most recent commit is minor. Should be fine. Somebody else should give it a once-over before merging, but from my perspective this is good to go. |
Do you have admin access on travis? To restart builds etc? |
No on upstream I don't think |
Did I miss anything or is this good to go? |
LGTM. @ctk3b anything else, or are we good to merge? |
Sorry I missed this - LGTM! |
Dicussed in #157, but to repeat the important bit:
Currently there's a bit of code at the beginning of
Forcefield.createSystem
that manages the atomtyping step, whereas this should more cleanly done by being sectioned off to a different function.I'm open to naming the function something more elegant, I'm not happy with
Forcefield.run_atomtyping
but couldn't come up with something better.I'm not sure if it should be a helper function, or whatever
Forcefield._run_atomtyping
would be called. It seems possible for a user to want to call it directly without creating the entireopenmm.System
orparmed.Structure
.I don't think a test is necessary for this, as I'm just moving code around. But I also couldn't think of how a useful test would be structured. I could verify that the returned
openmm.Topology
has atomtype information, but this should cause later tests to crash anyway.I added
use_residue_map
as an argument toForcefield.apply
. I don't know why it wasn't there before, and don't see any reason for it to be buried inside these other functions.