Using python console to rotate a molecule in Avogadro

Hello,

I have been experimenting with the Avogadro python interface and I have a question. I am trying to rotate the whole molecule, and after googling a bit I came up with a procedure that I think should work, but gives an error when I run it.

To start with I used the GUI to build and minimize chloromethane, then I entered this into the Python console:

import Avogadro
import numpy
import math

mol = Avogadro.molecule
a = math.cos( math.radians(-30.0) )
b = math.sin( math.radians(-30.0) )
R = numpy.mat( [[a, -b, 0], [b, a, 0], [0,0,1]] )
for a in mol.atoms:
… newpos = mol.atom(a.index).pos * R;
… newpos = newpos.T;
… mol.atom(a.index).pos = newpos

Traceback (most recent call last):
File “”, line 1, in
SystemError: NULL result without error in PyObject_Call

Just to see if I could get something that works I picked an arbitrary angle of -30 degrees. I am afraid that my matrix algebra skills are quite out of date and I could be misunderstanding something simple about the mathematics or about numpy.

Can anyone help me with this?

Thanks,

Steve

On Tue, Jul 26, 2011 at 7:49 PM, Steven Wathen SWATHEN@sienaheights.edu wrote:

Hello,

I have been experimenting with the Avogadro python interface and I have a question. I am trying to rotate the whole molecule, and after googling a bit I came up with a procedure that I think should work, but gives an error when I run it.

To start with I used the GUI to build and minimize chloromethane, then I entered this into the Python console:

import Avogadro
import numpy
import math

mol = Avogadro.molecule
a = math.cos( math.radians(-30.0) )
b = math.sin( math.radians(-30.0) )
R = numpy.mat( [[a, -b, 0], [b, a, 0], [0,0,1]] )
for a in mol.atoms:
… newpos = mol.atom(a.index).pos * R;
… newpos = newpos.T;
… mol.atom(a.index).pos = newpos

Traceback (most recent call last):
File “”, line 1, in
SystemError: NULL result without error in PyObject_Call

Just to see if I could get something that works I picked an arbitrary angle of -30 degrees. I am afraid that my matrix algebra skills are quite out of date and I could be misunderstanding something simple about the mathematics or about numpy.

In C++, the Atom::pos() function returns an Eigen vector, which is by
default a column vector. I’m not sure what is returned in python, but
try

newpos = R * mol.atom(a.index).pos
mol.atom(a.index).pos = newpos

and see if that clears it up. The transpose shouldn’t be necessary.

If I remember python correctly, You may be able to replace
"mol.atom(a.index).pos" with just “a.pos”, unless the python wrappers
are doing something unexpected. If so, you may be able write the
entire loop body as

a.pos = R * a.pos

Hope this helps,

Dave

Hi David,

Thanks for the tip.

I tried your suggestions and I still get an error:

Leaving out the transpose gives the same result as before:

for a in mol.atoms:
… newpos = mol.atom(a.index).pos * R;
… mol.atom(a.index).pos = newpos

Traceback (most recent call last):
File “”, line 1, in
SystemError: NULL result without error in PyObject_Call

You suggestion to simplify the loop also gives an error, but a different one:

for a in mol.atoms:
… a.pos = R * a.pos

Traceback (most recent call last):
File “”, line 1, in
File “/usr/lib/python2.6/dist-packages/numpy/core/defmatrix.py”, line 290, in mul
return N.dot(self, asmatrix(other))
ValueError: matrices are not aligned

I’m afraid I don’t know how to interpret the error messages. Any advice would be appreciated.

Thanks,

Steve


From: David Lonie [loniedavid@gmail.com]
Sent: Tuesday, July 26, 2011 8:12 PM
To: Steven Wathen
Cc: Avogadro-devel Devel
Subject: Re: [Avogadro-devel] using python console to rotate a molecule in Avogadro

On Tue, Jul 26, 2011 at 7:49 PM, Steven Wathen SWATHEN@sienaheights.edu wrote:

Hello,

I have been experimenting with the Avogadro python interface and I have a question. I am trying to rotate the whole molecule, and after googling a bit I came up with a procedure that I think should work, but gives an error when I run it.

To start with I used the GUI to build and minimize chloromethane, then I entered this into the Python console:

import Avogadro
import numpy
import math

mol = Avogadro.molecule
a = math.cos( math.radians(-30.0) )
b = math.sin( math.radians(-30.0) )
R = numpy.mat( [[a, -b, 0], [b, a, 0], [0,0,1]] )
for a in mol.atoms:
… newpos = mol.atom(a.index).pos * R;
… newpos = newpos.T;
… mol.atom(a.index).pos = newpos

Traceback (most recent call last):
File “”, line 1, in
SystemError: NULL result without error in PyObject_Call

Just to see if I could get something that works I picked an arbitrary angle of -30 degrees. I am afraid that my matrix algebra skills are quite out of date and I could be misunderstanding something simple about the mathematics or about numpy.

In C++, the Atom::pos() function returns an Eigen vector, which is by
default a column vector. I’m not sure what is returned in python, but
try

newpos = R * mol.atom(a.index).pos
mol.atom(a.index).pos = newpos

and see if that clears it up. The transpose shouldn’t be necessary.

If I remember python correctly, You may be able to replace
"mol.atom(a.index).pos" with just “a.pos”, unless the python wrappers
are doing something unexpected. If so, you may be able write the
entire loop body as

a.pos = R * a.pos

Hope this helps,

Dave

I have come up with a solution, although there is probably a better way to do it. In case it might be useful anyone else I thought I would share it with the list.

The data type of the rotated position doesn’t seem to match, so you can’t use it to set a new atom.pos. I pulled out the new x, y, and z coordinates and used them to make a new numpy.array() which can be used to set the atom.pos.

I also added a line to center the molecule.

import Avogadro
import numpy
import math

mol = Avogadro.molecule

a = math.cos( math.radians(-30.0) )
b = math.sin( math.radians(-30.0) )

rotation matrix, 30 degrees clockwise

R = numpy.mat( [[a, -b, 0], [b, a, 0], [0,0,1]] )

mol.translate(-mol.center)

for a in mol.atoms:
newpos = mol.atom(a.index).pos * R;
newx = newpos[0,0];
newy = newpos[0,1];
newz = newpos[0,2];
mol.atom(a.index).pos = numpy.array([newx, newy, newz])

Thanks,

Steve


From: Steven Wathen
Sent: Wednesday, July 27, 2011 11:07 AM
To: Avogadro-devel Devel
Subject: Re: [Avogadro-devel] using python console to rotate a molecule in Avogadro

Hi David,

Thanks for the tip.

I tried your suggestions and I still get an error:

Leaving out the transpose gives the same result as before:

for a in mol.atoms:
… newpos = mol.atom(a.index).pos * R;
… mol.atom(a.index).pos = newpos

Traceback (most recent call last):
File “”, line 1, in
SystemError: NULL result without error in PyObject_Call

You suggestion to simplify the loop also gives an error, but a different one:

for a in mol.atoms:
… a.pos = R * a.pos

Traceback (most recent call last):
File “”, line 1, in
File “/usr/lib/python2.6/dist-packages/numpy/core/defmatrix.py”, line 290, in mul
return N.dot(self, asmatrix(other))
ValueError: matrices are not aligned

I’m afraid I don’t know how to interpret the error messages. Any advice would be appreciated.

Thanks,

Steve


From: David Lonie [loniedavid@gmail.com]
Sent: Tuesday, July 26, 2011 8:12 PM
To: Steven Wathen
Cc: Avogadro-devel Devel
Subject: Re: [Avogadro-devel] using python console to rotate a molecule in Avogadro

On Tue, Jul 26, 2011 at 7:49 PM, Steven Wathen SWATHEN@sienaheights.edu wrote:

Hello,

I have been experimenting with the Avogadro python interface and I have a question. I am trying to rotate the whole molecule, and after googling a bit I came up with a procedure that I think should work, but gives an error when I run it.

To start with I used the GUI to build and minimize chloromethane, then I entered this into the Python console:

import Avogadro
import numpy
import math

mol = Avogadro.molecule
a = math.cos( math.radians(-30.0) )
b = math.sin( math.radians(-30.0) )
R = numpy.mat( [[a, -b, 0], [b, a, 0], [0,0,1]] )
for a in mol.atoms:
… newpos = mol.atom(a.index).pos * R;
… newpos = newpos.T;
… mol.atom(a.index).pos = newpos

Traceback (most recent call last):
File “”, line 1, in
SystemError: NULL result without error in PyObject_Call

Just to see if I could get something that works I picked an arbitrary angle of -30 degrees. I am afraid that my matrix algebra skills are quite out of date and I could be misunderstanding something simple about the mathematics or about numpy.

In C++, the Atom::pos() function returns an Eigen vector, which is by
default a column vector. I’m not sure what is returned in python, but
try

newpos = R * mol.atom(a.index).pos
mol.atom(a.index).pos = newpos

and see if that clears it up. The transpose shouldn’t be necessary.

If I remember python correctly, You may be able to replace
"mol.atom(a.index).pos" with just “a.pos”, unless the python wrappers
are doing something unexpected. If so, you may be able write the
entire loop body as

a.pos = R * a.pos

Hope this helps,

Dave


Got Input? Slashdot Needs You.
Take our quick survey online. Come on, we don’t ask for help often.
Plus, you’ll get a chance to win $100 to spend on ThinkGeek.
http://p.sf.net/sfu/slashdot-survey


Avogadro-devel mailing list
Avogadro-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/avogadro-devel