[MMTK] Re: Defining ciclobutadiene

Konrad Hinsen hinsen@cnrs-orleans.fr
Wed, 3 Mar 1999 11:16:45 +0100

> I'm sorry to be such a pain in the rear but I have corrected the
> Z-Matrix:

> and I get a *very* similar error message:
>   File "/usr/local/mmtk/ConfigIO.py", line 169, in findPositions
>     pos3 = self.coordinates[entry[5]]
> KeyError: <Atom number 3>

This time you found a bug in MMTK (and in one of its oldest parts!).
The geometrical construction of the atom positions doesn't work
for your rather special case with plenty of right angles and
zero dihedrals.

To fix the bug, replace the class ZMatrix in the file ConfigIO.py
by the following one:

class ZMatrix:

    def __init__(self, data):
	self.data = data
	self.coordinates = {}

    substitute = 1

    def findPositions(self):
	# First atom at origin
	self.coordinates[self.data[0][0]] = Vector(0,0,0)
	# Second atom along x-axis
	self.coordinates[self.data[1][0]] = Vector(self.data[1][2],0,0)
	# Third atom in xy-plane
            pos1 = self.coordinates[self.data[2][1]]
        except KeyError:
            raise ValueError, \
                  "atom %d has no defined position" % self.data[2][1].number
            pos2 = self.coordinates[self.data[2][3]]
        except KeyError:
            raise ValueError, \
                  "atom %d has no defined position" % self.data[2][3].number
	sphere = Sphere(pos1, self.data[2][2])
	cone = Cone(pos1, pos2-pos1, self.data[2][4])
	plane = Plane(Vector(0,0,0), Vector(0,0,1))
	points = sphere.intersectWith(cone).intersectWith(plane)
	self.coordinates[self.data[2][0]] = points[0]
	# All following atoms defined by distance + angle + dihedral
	for entry in self.data[3:]:
                pos1 = self.coordinates[entry[1]]
            except KeyError:
                raise ValueError, \
                      "atom %d has no defined position" % entry[1].number
                pos2 = self.coordinates[entry[3]]
            except KeyError:
                raise ValueError, \
                      "atom %d has no defined position" % entry[3].number
                pos3 = self.coordinates[entry[5]]
            except KeyError:
                raise ValueError, \
                      "atom %d has no defined position" % entry[5].number
	    distance = entry[2]
	    angle = entry[4]
	    dihedral = entry[6]
	    sphere = Sphere(pos1, distance)
	    cone = Cone(pos1, pos2-pos1, angle)
	    plane123 = Plane(pos3, pos2, pos1)
            points = sphere.intersectWith(cone).intersectWith(plane123)
            for p in points:
                if Plane(pos2, pos1, p).normal * plane123.normal > 0:
            p = rotatePoint(p, Line(pos1, pos2-pos1), dihedral)
            self.coordinates[entry[0]] = p

    def applyTo(self, object):
	if not len(self.coordinates):
	for entry in self.coordinates.items():
	    object.setPosition(entry[0], entry[1])

With that definition I can construct your molecule; I think you still
need to correct one angle to make it come out right.

Konrad Hinsen                            | E-Mail: hinsen@cnrs-orleans.fr
Centre de Biophysique Moleculaire (CNRS) | Tel.: +33-
Rue Charles Sadron                       | Fax:  +33-
45071 Orleans Cedex 2                    | Deutsch/Esperanto/English/
France                                   | Nederlands/Francais