Created
February 2, 2021 14:53
-
-
Save matteoferla/a241001c033b89bc69c1d1317bc59dda to your computer and use it in GitHub Desktop.
For Fragmenstein. A draft of a potential way to remove atoms from a 3D embedded set of molecules, when 2D is too misleading and overlap is key.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# NGLView is a great way to see a set of rdkit.Chem molecules in 3D. | |
# Right clicking gives green spheres by default. Right clicking on a sphere removes it. So nice way to keep track | |
# the `ModNGL` object contains the dynamic property `picked_atoms` which lists the atoms that were clicked. | |
# Clicked twice is removed. However, there is no way to determine the button integer (left, middle, wheel, right). | |
# Before loading the mols from rdkit it would be nice to fill the PDB info. | |
# As seen in https://blog.matteoferla.com/2020/03/atom-names-purely-in-rdkit.html | |
# once one has the atom names one can delete the atoms off a ``rdkit.Chem.RWMol`` making it nice and clear for Fragmenstein. | |
import nglview as nv | |
from io import StringIO | |
from typing import * | |
import json | |
from IPython.display import display | |
from collections import defaultdict | |
class ModNGL(nv.NGLWidget): | |
picked_atoms = [] | |
@observe('picked') | |
def my_picked(self, change): | |
""" | |
This does not override the `_on_picked` method, that when initialised by | |
`view.player._make_widget_picked` fills `view.player.widget_picked.value`. | |
It however is strongly influenced by it! | |
Unfortunately, there's no way to tell in Python if left or right was clicked. | |
Technically in JS, the `buttons` integer passed to `clicked` controls this, | |
but it is not stored. | |
"picked" is a trait and is configured on both Python and JS. | |
So I doubt a pure Python solution is possible. | |
""" | |
print(buttons) | |
if change['new']: | |
self.picked_atoms.append(change['new']) | |
@property | |
def picked_atoms(self) -> Dict[List[str]]: | |
""" | |
Returns a dict with keys component indices and values a list of atom names sensu NGL | |
``[LIG]1:A.O1`` So [residue name] residue index : chain . atom name | |
""" | |
compontent_atoms = defaultdict(list) | |
for atom in self.picked_atoms: | |
name = atom['atom1']['name'] | |
comp = compontent_atoms[atom['component']] | |
if name in comp: | |
del comp[comp.index(name)] | |
else: | |
comp.append(name) | |
return compontent_atoms | |
# ------------------------------------------------------------------------------------------------------------------------ | |
def show_mols(*mols: Chem.Mol) -> nv.NGLWidget: | |
view = ModNGL() | |
for mol in (acetyl, ethylamine): | |
fh = StringIO(Chem.MolToPDBBlock(mol)) | |
view.add_component(fh, ext='pdb') | |
#view.player._make_widget_picked() | |
return view | |
view = show_mols(acetyl, ethylamine) | |
view |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment