Skip to content
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

added stubs for Molecule conversions #58

Merged
merged 15 commits into from
Feb 24, 2022
Merged

Conversation

richardjgowers
Copy link
Contributor

@richardjgowers richardjgowers commented Feb 16, 2022

added Molecule conversion methods

@codecov
Copy link

codecov bot commented Feb 16, 2022

Codecov Report

Merging #58 (d047c94) into main (6c888af) will increase coverage by 0.24%.
The diff coverage is 96.87%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main      #58      +/-   ##
==========================================
+ Coverage   98.30%   98.55%   +0.24%     
==========================================
  Files          25       37      +12     
  Lines         473      691     +218     
==========================================
+ Hits          465      681     +216     
- Misses          8       10       +2     
Impacted Files Coverage Δ
openfe/setup/__init__.py 100.00% <ø> (ø)
openfe/tests/setup/test_molecule.py 96.61% <94.11%> (-3.39%) ⬇️
openfe/setup/atommapper.py 100.00% <100.00%> (ø)
openfe/setup/atommapping.py 100.00% <100.00%> (ø)
openfe/setup/lomap_mapper.py 100.00% <100.00%> (ø)
openfe/setup/molecule.py 100.00% <100.00%> (ø)
openfe/utils/__init__.py 100.00% <100.00%> (ø)
openfe/utils/typing.py 100.00% <100.00%> (ø)
openfecli/parameters/__init__.py 100.00% <0.00%> (ø)
openfecli/tests/parameters/test_utils.py 100.00% <0.00%> (ø)
... and 9 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6c888af...d047c94. Read the comment docs.

Copy link
Member

@dwhswenson dwhswenson left a comment

Choose a reason for hiding this comment

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

I'm a little unsure about implicitly treating all arguments with this, although I suppose a user who really needs both our Molecule and rdkit.Mol can just avoid using the decorator (mol.rdkit is not a heavy piece of boilerplate).

A couple alternatives that might be worth considering:

  1. Require argument names in the decorator, so you decorate as @as_rdkit('mol1', 'mol2'). For implementation, inspect.Signature.bind can do most of the heavy lifting to correctly associate argument name with value passed by user, whether in args or kwargs.
  2. If we only need this on AtomMappers, then it might be more straightforward to subclass as RDKitAtomMapper, etc. (But I suspect may be are other places where this will be useful, even if my tired brain can't think of them this morning.)

Not that either of those are necessarily better, but they're worth consideration.

I'm definitely +1 on the Molecule.oechem, Molecule.openff properties.

Handling kwargs in the decorators is the only thing I see as a required change. We can't know whether the user is passing the molecules as args or kwargs.

def as_rdkit(func):
@wraps(func)
def inner(*args, **kwargs):
args = (a.rdkit if isinstance(a, Molecule) else a for a in args)
Copy link
Member

Choose a reason for hiding this comment

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

definitely need to treat kwargs as well (in this and other decorator)

@richardjgowers
Copy link
Contributor Author

richardjgowers commented Feb 16, 2022 via email

@@ -10,6 +10,7 @@ dependencies:
- pytest-xdist
- pytest-cov
- coverage
- openff-toolkit
Copy link
Member

Choose a reason for hiding this comment

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

add jaimergp/label/unsupported-cudatoolkit-shim to channels above and channel-priority: strict to the conda-incubator/setup-miniconda@v2 in the ci.yaml file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nah I think we're just sucking it up and installing cuda

Copy link
Member

Choose a reason for hiding this comment

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

are we treating environment.yml as something users will use?

Copy link
Member

Choose a reason for hiding this comment

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

I would think perhaps code contributors, but not users -- env for users is defined by the recipe in the feedstock

Copy link
Member

Choose a reason for hiding this comment

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

In that case I'm not sure why we would needlessly slowdown CI by not including the shim?

@pep8speaks
Copy link

pep8speaks commented Feb 21, 2022

Hello @richardjgowers! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻

Comment last updated at 2022-02-24 16:17:42 UTC

Copy link
Member

@dwhswenson dwhswenson left a comment

Choose a reason for hiding this comment

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

Main issue is that I don't think its good to drop Windows support entirely. At least, I will entirely rely on CI to tell me that code still runs on Win, and I thought that was an important target for our users, especially in the setup stage.

Otherwise, please change the title -- these are no longer stubs; it's the full molecule conversion! (At least, in the "to" direction.) 😊

.github/workflows/ci.yaml Show resolved Hide resolved
openfe/setup/molecule.py Show resolved Hide resolved
@richardjgowers
Copy link
Contributor Author

richardjgowers commented Feb 22, 2022 via email

@richardjgowers
Copy link
Contributor Author

@dwhswenson what do you think about renaming the .rdkit etc to to_rdkit() to a) match OFF and b) make it clearer that a copy is happening?

@dwhswenson
Copy link
Member

@dwhswenson what do you think about renaming the .rdkit etc to to_rdkit() to a) match OFF and b) make it clearer that a copy is happening?

Mixed feelings. I see the value in matching OFF. Do we actually intend this to be a copy, though? I thought we were going to cache it. (I did the copy on the input via from_rdkit).

That said, if we make it a copy on output, then I think making it a method, not property, is required. Otherwise you get mol.rdkit is not mol.rdkit.

@richardjgowers
Copy link
Contributor Author

richardjgowers commented Feb 23, 2022 via email

@dwhswenson
Copy link
Member

Yeah, these are good points on why returning a copy is a good idea. In that case, I'm strongly in favor of to_rdkit(). I think that if we return a copy, it should be mol.to_rdkit(); if we cache the object once created and always return the cached, it should be mol.rdkit.

Comment on lines 30 to +61
def __init__(self, rdkit: RDKitMol, name: str = ""):
self._rdkit = rdkit
# internally we store as RDKit, for now...
self._rdkit = Chem.Mol(rdkit)
self._hash = hashmol(self._rdkit, name=name)

# property for immutability; also may allow in-class type conversion
@property
def rdkit(self) -> RDKitMol:
"""RDKit representation of this molecule"""
return self._rdkit
def to_rdkit(self) -> RDKitMol:
"""Return an RDKit copied representation of this molecule"""
return Chem.Mol(self._rdkit)

@classmethod
def from_rdkit(cls, rdkit: RDKitMol, name: str = ""):
"""Create a Molecule copying the input from an rdkit Mol"""
return cls(rdkit=Chem.Mol(rdkit), name=name)

def to_openeye(self) -> OEMol:
"""OEChem representation of this molecule"""
return self.to_openff().to_openeye()

@classmethod
def from_openeye(cls, oemol: OEMol, name: str = ""):
raise NotImplementedError

def to_openff(self) -> OFFMolecule:
"""OpenFF Toolkit representation of this molecule"""
m = OFFMolecule(self._rdkit, allow_undefined_stereo=True)
m.name = self.name

return m

@classmethod
def from_openff(cls, openff: OFFMolecule, name: str = ""):
raise NotImplementedError
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dwhswenson so what I've done here is everything is a copy. So on creation, we copy the rdkit Mol, and all to_X are copies. The Molecule is then therefore read-only (and documented as such). Handling manipulation of a Molecule is out of scope for us (i.e. if you want to change a Molecule, recreate it).

Copy link
Member

Choose a reason for hiding this comment

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

100% agree with the approach. Reviewing details now.

Copy link
Member

@dwhswenson dwhswenson left a comment

Choose a reason for hiding this comment

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

2 minor suggestions; otherwise LGTM. Please make those changes unless they don't make sense, but marking this approved; I don't think I need to review after changes.

@classmethod
def from_rdkit(cls, rdkit: RDKitMol, name: str = ""):
"""Create a Molecule copying the input from an rdkit Mol"""
return cls(rdkit=Chem.Mol(rdkit), name=name)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return cls(rdkit=Chem.Mol(rdkit), name=name)
return cls(rdkit=rdkit, name=name)

since we copy in the __init__, no need to double the copying here.

import pytest

try:
from openeye import oechem
except ImportError:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
except ImportError:
except ImportError: # -no-cov-

looks like this line codecov is complaining about this; maybe we add something for the test matrix to test against a minimal set of reqs? For now, ignore coverage here.

@richardjgowers richardjgowers merged commit 3579a01 into main Feb 24, 2022
@richardjgowers richardjgowers deleted the Molecule_converts branch February 24, 2022 21:02
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.

5 participants