Hi Markus,

On Thu, Aug 21, 2008 at 1:34 PM, markus <[email protected]> wrote:
> Hi,
> somehow I do not get the way RDKit organizes the IDs of conformers:

Yes, the way conformers is handled is confusing at first.

First I'll show you how to do what I think you were trying to do, then
I'll try and explain what the problem was:

>  >>> from Chem import AllChem as Chem
>  >>> import copy
>  >>> mol=Chem.MolFromSmiles('c1ccccc1N')
>  >>> Chem.EmbedMultipleConfs(mol,10)
> <rdBase._vecti object at 0x8301e2c>
>  >>> mol2=copy.deepcopy(mol)
>  >>> for i in range(mol.GetNumConformers()):
> ...     print mol.GetConformer(i)
> ...

The best way to loop over a molecule's conformers is using its
GetConformers() method:

[14]>>> m = Chem.MolFromSmiles('c1ccccc1N')
[15]>>> AllChem.EmbedMultipleConfs(m,10)
Out[15] <rdBase._vecti object at 0x218182c>
[16]>>> [conf.GetId() for conf in m.GetConformers()]
Out[16] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

The molecule's GetConformer(x) method doesn't actually return the
conformer with index X, it returns the conformer with ID x. This is
what causes the problem here:

>  >>> mol.AddConformer(mol2.GetConformer(4))
> 4
>  >>> print 'NumConfs: %d\n' %(mol.GetNumConformers())
> NumConfs: 11
>
>  >>> for i in range(mol.GetNumConformers()):
> ...     print mol.GetConformer(i)
> ...
> <Chem.rdchem.Conformer object at 0x831448c>
> <Chem.rdchem.Conformer object at 0x831448c>
> <Chem.rdchem.Conformer object at 0x831448c>
> <Chem.rdchem.Conformer object at 0x831448c>
> <Chem.rdchem.Conformer object at 0x831448c>
> <Chem.rdchem.Conformer object at 0x831448c>
> <Chem.rdchem.Conformer object at 0x831448c>
> <Chem.rdchem.Conformer object at 0x831448c>
> <Chem.rdchem.Conformer object at 0x831448c>
> <Chem.rdchem.Conformer object at 0x831448c>
> Traceback (most recent call last):
>  File "<stdin>", line 2, in <module>
> ValueError: Bad Conformer Id
>  >>>

Continuing my example from above will help show what went wrong :
[17]>>> m2 = copy.deepcopy(m)
[18]>>> m.AddConformer(m2.GetConformer(4))
Out[18] 4
[21]>>> [conf.GetId() for conf in m.GetConformers()]
Out[21] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 4]

You can see that there are two conformers with id 4, but none with id
10, which is what you were trying to retrieve above. Note that the
second conformer with id 4 cannot be retrieved using m.GetConformer :
that always returns the first conformer with the corresponding Id.

> Why can't I iterate over the conformers the second time?
> Do I have to assign a ConfID explicitly, when adding a Conformer?

No, you don't. But if you're adding a conformer to a molecule that
already has a set of conformers, you might want to use the optional
assignId argument to Mol.AddConformer to tell the molecule to
automatically assign a new Id:

[22]>>> m.AddConformer(m2.GetConformer(5),assignId=True)
Out[22] 10
[23]>>> [conf.GetId() for conf in m.GetConformers()]
Out[23] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 4, 10]

To summarize and expand a bit:
A molecule's conformers don't have to have sequential ids and the ids
can be arbitrary positive values. So if a molecule has 10 conformers,
you can't be sure that mol.GetConformer(3) will work. If you want to
loop over a molecule's conformers use the GetConformers() method.

I hope this helps,
-greg

Reply via email to