0

I defined a subclass of Atom in rdkit.Chem. I also defined an instance attribute in it but I could not get that instance from RWMol object in rdkit.

Below there is a sample code for my problem:

from rdkit import Chem

class MyAtom(Chem.Atom):

    def __init__(self, symbol, **kwargs):
        super().__init__(symbol, **kwargs)
        self.my_attribute = 0

    def get_my_attribute(self):
        return self.my_attribute

if __name__ == '__main__':
    rw_mol = Chem.RWMol()

    # I created MyAtom class object then added to RWMol. But I couldn't get it again.
    my_atom = MyAtom('C')
    my_atom.my_attribute = 3

    rw_mol.AddAtom(my_atom)
    atom_in_mol = rw_mol.GetAtoms()[0]

    # I can access my_atom new defined attributes.
    print(my_atom.get_my_attribute())

    # below two line gives error: AttributeError: 'Atom' object has no attribute 'get_my_attribute'
    print(atom_in_mol.get_my_attribute())
    print(atom_in_mol.my_attribute)

    # type(atom1): <class '__main__.MyAtom'>
    # type(atom_in_mol): <class 'rdkit.Chem.rdchem.Atom'>
    # Why below atom types are different? Thanks to polymorphism, that two object types must be same.

Normally this code must run but it gives error due to last line because atom_in_mol object type is Chem.Atom. But should it be MyAtom? I also cannot access my_attribute directly.

rdkit Python library is a wrapper of C++. So is the problem this? Cannot I use inheritance for this library?

Note: I researched rdkit documentation and there is a SetProp method for saving values in atoms. It uses dictionary to save values. It runs fine but it is too slow for my project. I want to use instance attributes to save my extra values. Is there any solution for that inheritance problem, or faster different solution?

1 Answers1

1

Python RDKit library is a C++ wrapper, so sometimes it does not follows the conventional Python object handling.

To go deeper, you will have to dig through the source code:

rw_mol.AddAtom(my_atom)

Above will execute AddAtom method in rdkit/Code/GraphMol/Wrap/Mol.cpp, which, in turn, calls addAtom method in rdkit/Code/GraphMol/RWMol.h, which then calls addAtom method in rdkit/Code/GraphMol/ROMol.cpp with default argument of updateLabel = true and takeOwnership = false.

The takeOwnership = false condition makes the argument atom to be duplicated,

// rdkit/Code/GraphMol/ROMol.cpp
if (!takeOwnership)
  atom_p = atom_pin->copy();
else
  atom_p = atom_pin;

Finally, if you look into what copy method do in rdkit/Code/GraphMol/Atom.cpp

Atom *Atom::copy() const {
  auto *res = new Atom(*this);
  return res;
}

So, it reinstantiate Atom class and returns it.

Sunhwan Jo
  • 2,293
  • 1
  • 15
  • 13