def get_transformation(self, molecule): atom1, atom2 = self.hinge_atoms center = molecule.coordinates[atom1] axis = molecule.coordinates[atom1] - molecule.coordinates[atom2] axis /= numpy.linalg.norm(axis) angle = numpy.random.uniform(-self.max_amplitude, self.max_amplitude) return rotation_around_center(center, angle, axis)
def do(self): transformation = rotation_around_center( self.parameters.center, math.pi, self.parameters.normal, True ) for victim in context.application.cache.translated_nodes: primitive.Transform(victim, transformation)
def test_center_ses2(self): from molmod.ext import center_ses2 for i in xrange(1000): close1 = numpy.random.uniform(0, 5, 3) close1_radius = numpy.random.uniform(0, 5) close2 = numpy.random.uniform(0, 5, 3) close2_radius = numpy.random.uniform(0, 5) probe = numpy.random.uniform(0, 5, 3) center = numpy.zeros(3, float) result = bool( center_ses2(probe, close1, close1_radius, close2, close2_radius, center)) check_result = ((numpy.linalg.norm(close1 - close2) > close1_radius + close2_radius) or (numpy.linalg.norm(close1 - close2) < abs(close1_radius - close2_radius))) self.assertEqual(result, check_result) if result == False: # test distances self.assertAlmostEqual(numpy.linalg.norm(center - close1), close1_radius) self.assertAlmostEqual(numpy.linalg.norm(center - close2), close2_radius) # test coplanarity mat = numpy.array([ probe - center, probe - close1, probe - close2, ]) self.assertAlmostEqual(numpy.linalg.det(mat), 0) # define a rotation of 180 degrees about the close1-close2 axis rotation = rotation_around_center(close1, numpy.pi, close2 - close1) new_center = rotation.vector_apply(center) # test if the rotated center also satisfies the distances and the coplanarity self.assertAlmostEqual(numpy.linalg.norm(new_center - close1), close1_radius) self.assertAlmostEqual(numpy.linalg.norm(new_center - close2), close2_radius) # test coplanarity mat = numpy.array([ probe - new_center, probe - close1, probe - close2, ]) self.assertAlmostEqual(numpy.linalg.det(mat), 0) # test if the center is closes to the probe than new_center self.assert_( numpy.linalg.norm(center - probe) < numpy.linalg.norm(new_center - probe))
def get_transformation(self, molecule): atom1, atom2, atom3 = self.hinge_atoms center = molecule.coordinates[atom2] a = molecule.coordinates[atom1] - molecule.coordinates[atom2] b = molecule.coordinates[atom3] - molecule.coordinates[atom2] axis = numpy.cross(a, b) norm = numpy.linalg.norm(axis) if norm < 1e-5: # We suppose that atom3 is part of the affected atoms axis = random_orthonormal(a) else: axis /= numpy.linalg.norm(axis) angle = numpy.random.uniform(-self.max_amplitude, self.max_amplitude) return rotation_around_center(center, angle, axis)
def test_center_ses2(self): from molmod.ext import center_ses2 for i in xrange(1000): close1 = numpy.random.uniform(0, 5, 3) close1_radius = numpy.random.uniform(0, 5) close2 = numpy.random.uniform(0, 5, 3) close2_radius = numpy.random.uniform(0, 5) probe = numpy.random.uniform(0, 5, 3) center = numpy.zeros(3, float) result = bool(center_ses2(probe, close1, close1_radius, close2, close2_radius, center)) check_result = ( (numpy.linalg.norm(close1 - close2) > close1_radius + close2_radius) or (numpy.linalg.norm(close1 - close2) < abs(close1_radius - close2_radius)) ) self.assertEqual(result, check_result) if result == False: # test distances self.assertAlmostEqual(numpy.linalg.norm(center-close1), close1_radius) self.assertAlmostEqual(numpy.linalg.norm(center-close2), close2_radius) # test coplanarity mat = numpy.array([ probe - center, probe - close1, probe - close2, ]) self.assertAlmostEqual(numpy.linalg.det(mat), 0) # define a rotation of 180 degrees about the close1-close2 axis rotation = rotation_around_center(close1, numpy.pi, close2-close1) new_center = rotation.vector_apply(center) # test if the rotated center also satisfies the distances and the coplanarity self.assertAlmostEqual(numpy.linalg.norm(new_center-close1), close1_radius) self.assertAlmostEqual(numpy.linalg.norm(new_center-close2), close2_radius) # test coplanarity mat = numpy.array([ probe - new_center, probe - close1, probe - close2, ]) self.assertAlmostEqual(numpy.linalg.det(mat), 0) # test if the center is closes to the probe than new_center self.assert_(numpy.linalg.norm(center - probe) < numpy.linalg.norm(new_center - probe))
def random_dimer(molecule0, molecule1, thresholds, shoot_max, max_tries=1000): """Create a random dimer. molecule0 and molecule1 are placed in one reference frame at random relative positions. Interatomic distances are above the thresholds. Initially a dimer is created where one interatomic distance approximates the threshold value. Then the molecules are given an additional separation in the range [0,shoot_max]. thresholds has the following format: {frozenset([atom_number1, atom_number2]): distance} """ # apply a random rotation to molecule1 center = numpy.zeros(3, float) angle = numpy.random.uniform(0, 2*numpy.pi) axis = random_unit(3) rotation = rotation_around_center(center, angle, axis) cor1 = numpy.dot(molecule1.coordinates, rotation.r) # select a random atom in each molecule atom0 = numpy.random.randint(len(molecule0.numbers)) atom1 = numpy.random.randint(len(molecule1.numbers)) # define a translation of molecule1 that brings both atoms in overlap delta = molecule0.coordinates[atom0] - cor1[atom1] cor1 += delta # define a random direction direction = random_unit(3) cor1 += 1*direction # move molecule1 along this direction until all intermolecular atomic # distances are above the threshold values threshold_mat = numpy.zeros((len(molecule0.numbers), len(molecule1.numbers)), float) distance_mat = numpy.zeros((len(molecule0.numbers), len(molecule1.numbers)), float) for i1, n1 in enumerate(molecule0.numbers): for i2, n2 in enumerate(molecule1.numbers): threshold = thresholds.get(frozenset([n1,n2])) threshold_mat[i1,i2] = threshold**2 while True: cor1 += 0.1*direction distance_mat[:] = 0 for i in 0,1,2: distance_mat += numpy.subtract.outer(molecule0.coordinates[:,i], cor1[:,i])**2 if (distance_mat > threshold_mat).all(): break # translate over a random distance [0,shoot] along the same direction # (if necessary repeat until no overlap is found) while True: cor1 += direction*numpy.random.uniform(0,shoot_max) distance_mat[:] = 0 for i in 0,1,2: distance_mat += numpy.subtract.outer(molecule0.coordinates[:,i], cor1[:,i])**2 if (distance_mat > threshold_mat).all(): break # done dimer = Molecule( numpy.concatenate([molecule0.numbers, molecule1.numbers]), numpy.concatenate([molecule0.coordinates, cor1]) ) dimer.direction = direction dimer.atom0 = atom0 dimer.atom1 = atom1 return dimer
def random_dimer(molecule0, molecule1, thresholds, shoot_max, max_tries=1000): """Create a random dimer. molecule0 and molecule1 are placed in one reference frame at random relative positions. Interatomic distances are above the thresholds. Initially a dimer is created where one interatomic distance approximates the threshold value. Then the molecules are given an additional separation in the range [0,shoot_max]. thresholds has the following format: {frozenset([atom_number1, atom_number2]): distance} """ # apply a random rotation to molecule1 center = numpy.zeros(3, float) angle = numpy.random.uniform(0, 2 * numpy.pi) axis = random_unit(3) rotation = rotation_around_center(center, angle, axis) cor1 = numpy.dot(molecule1.coordinates, rotation.r) # select a random atom in each molecule atom0 = numpy.random.randint(len(molecule0.numbers)) atom1 = numpy.random.randint(len(molecule1.numbers)) # define a translation of molecule1 that brings both atoms in overlap delta = molecule0.coordinates[atom0] - cor1[atom1] cor1 += delta # define a random direction direction = random_unit(3) cor1 += 1 * direction # move molecule1 along this direction until all intermolecular atomic # distances are above the threshold values threshold_mat = numpy.zeros( (len(molecule0.numbers), len(molecule1.numbers)), float) distance_mat = numpy.zeros( (len(molecule0.numbers), len(molecule1.numbers)), float) for i1, n1 in enumerate(molecule0.numbers): for i2, n2 in enumerate(molecule1.numbers): threshold = thresholds.get(frozenset([n1, n2])) threshold_mat[i1, i2] = threshold**2 while True: cor1 += 0.1 * direction distance_mat[:] = 0 for i in 0, 1, 2: distance_mat += numpy.subtract.outer(molecule0.coordinates[:, i], cor1[:, i])**2 if (distance_mat > threshold_mat).all(): break # translate over a random distance [0,shoot] along the same direction # (if necessary repeat until no overlap is found) while True: cor1 += direction * numpy.random.uniform(0, shoot_max) distance_mat[:] = 0 for i in 0, 1, 2: distance_mat += numpy.subtract.outer(molecule0.coordinates[:, i], cor1[:, i])**2 if (distance_mat > threshold_mat).all(): break # done dimer = Molecule(numpy.concatenate([molecule0.numbers, molecule1.numbers]), numpy.concatenate([molecule0.coordinates, cor1])) dimer.direction = direction dimer.atom0 = atom0 dimer.atom1 = atom1 return dimer