def add_hydrogens(atom): existing_bonds = list(atom.iter_bonds()) bond_length = bonds.get_length(atom.number, 1, BOND_SINGLE) num_hydrogens = self.parameters.num_hydrogens if len(existing_bonds) == 0: t = atom.transformation.t + numpy.array([0, bond_length, 0]) H = Atom(name="auto H", number=1, transformation=Translation(t)) primitive.Add(H, atom.parent) bond = Bond(name="aut H bond", targets=[atom, H]) primitive.Add(bond, atom.parent) existing_bonds.append(bond) num_hydrogens -= 1 main_direction = numpy.zeros(3, float) for bond in existing_bonds: shortest_vector = bond.shortest_vector_relative_to(atom.parent) if bond.children[1].target == atom: shortest_vector *= -1 main_direction += shortest_vector main_direction /= numpy.linalg.norm(main_direction) normal = random_orthonormal(main_direction) rotation = Rotation.from_properties( 2 * numpy.pi / float(num_hydrogens), main_direction, False) h_pos = bond_length * ( main_direction * numpy.cos(self.parameters.valence_angle) + normal * numpy.sin(self.parameters.valence_angle)) for i in range(num_hydrogens): t = atom.transformation.t + h_pos H = Atom(name="auto H", number=1, transformation=Translation(t)) primitive.Add(H, atom.parent) bond = Bond(name="aut H bond", targets=[atom, H]) primitive.Add(bond, atom.parent) h_pos = rotation * h_pos
def add_hydrogens(atom): existing_bonds = list(atom.iter_bonds()) bond_length = bonds.get_length(atom.number, 1, BOND_SINGLE) num_hydrogens = self.parameters.num_hydrogens if len(existing_bonds) == 0: t = atom.transformation.t + numpy.array([0,bond_length,0]) H = Atom(name="auto H", number=1, transformation=Translation(t)) primitive.Add(H, atom.parent) bond = Bond(name="aut H bond", targets=[atom, H]) primitive.Add(bond, atom.parent) existing_bonds.append(bond) num_hydrogens -= 1 main_direction = numpy.zeros(3, float) for bond in existing_bonds: shortest_vector = bond.shortest_vector_relative_to(atom.parent) if bond.children[1].target == atom: shortest_vector *= -1 main_direction += shortest_vector main_direction /= numpy.linalg.norm(main_direction) normal = random_orthonormal(main_direction) rotation = Rotation.from_properties(2*numpy.pi / float(num_hydrogens), main_direction, False) h_pos = bond_length*( main_direction*numpy.cos(self.parameters.valence_angle) + normal*numpy.sin(self.parameters.valence_angle) ) for i in range(num_hydrogens): t = atom.transformation.t + h_pos H = Atom(name="auto H", number=1, transformation=Translation(t)) primitive.Add(H, atom.parent) bond = Bond(name="aut H bond", targets=[atom, H]) primitive.Add(bond, atom.parent) h_pos = rotation * h_pos
def add_hydrogens(atom): existing_bonds = list(atom.iter_bonds()) num_bonds = len(existing_bonds) bond_length = bonds.get_length(atom.number, 1, BOND_SINGLE) if num_bonds == 0: t = atom.transformation.t + numpy.array([0, bond_length, 0]) H = Atom(name="auto H", number=1, transformation=Translation(t)) primitive.Add(H, atom.parent) bond = Bond(name="aut H bond", targets=[atom, H]) primitive.Add(bond, atom.parent) existing_bonds.append(bond) num_bonds = 1 used_valence = 0 oposite_direction = numpy.zeros(3, float) for bond in existing_bonds: shortest_vector = bond.shortest_vector_relative_to(atom.parent) if bond.children[1].target == atom: shortest_vector *= -1 oposite_direction -= shortest_vector if bond.bond_type == BOND_SINGLE: used_valence += 1 elif bond.bond_type == BOND_DOUBLE: used_valence += 2 elif bond.bond_type == BOND_TRIPLE: used_valence += 3 oposite_direction /= numpy.linalg.norm(oposite_direction) num_hydrogens = valence_el( atom.number) - 2 * lone_pairs(atom.number) - used_valence if num_hydrogens <= 0: return hybride_count = num_hydrogens + lone_pairs( atom.number) + num_bonds - (used_valence - num_bonds) num_sites = num_hydrogens + lone_pairs(atom.number) rotation = Rotation.from_properties( 2 * numpy.pi / float(num_sites), oposite_direction, False) opening_key = (hybride_count, num_sites) opening_angle = self.opening_angles.get(opening_key) if opening_angle is None: return if num_bonds == 1: first_bond = existing_bonds[0] other_atom = first_bond.children[0].target if other_atom == atom: other_atom = first_bond.children[1].target other_bonds = [ bond for bond in other_atom.iter_bonds() if bond != first_bond ] if len(other_bonds) > 0: normal = other_bonds[0].shortest_vector_relative_to( atom.parent) normal -= numpy.dot(normal, oposite_direction) * oposite_direction normal /= numpy.linalg.norm(normal) if other_bonds[0].children[0].target == other_atom: normal *= -1 else: normal = random_orthonormal(oposite_direction) elif num_bonds == 2: normal = numpy.cross( oposite_direction, existing_bonds[0].shortest_vector_relative_to(atom.parent)) normal /= numpy.linalg.norm(normal) elif num_bonds == 3: normal = random_orthonormal(oposite_direction) else: return h_pos = bond_length * (oposite_direction * numpy.cos(opening_angle) + normal * numpy.sin(opening_angle)) for i in range(num_hydrogens): t = atom.transformation.t + h_pos H = Atom(name="auto H", number=1, transformation=Translation(t)) primitive.Add(H, atom.parent) bond = Bond(name="aut H bond", targets=[atom, H]) primitive.Add(bond, atom.parent) h_pos = rotation * h_pos
def replace(self, gl_object): if not gl_object.get_fixed(): new = self.get_new(gl_object.transformation.t) # select a target object, i.e. the one the will be connected with # the bonds/vectors/... of the replaced object if (self.current_object == "Fragment"): # fragments are inserted as frames # take atom with index 1 as target target_object = new.children[1] else: target_object = new # check if all connections to the replaced object are applicable # to the new object. if not, then do not perform the replacement # and return early. for reference in gl_object.references[::-1]: if not reference.check_target(target_object): return # add the new object parent = gl_object.parent primitive.Add(new, parent) if (self.current_object == "Fragment"): # Fix the rotation and translation of the molecular fragment. # Rotation Bond = context.application.plugins.get_node("Bond") if len(gl_object.references) == 1 and isinstance( gl_object.references[0].parent, Bond): bond1 = gl_object.references[0].parent direction1 = bond1.shortest_vector_relative_to(parent) if bond1.children[0].target != gl_object: direction1 *= -1 bond2 = new.children[0].references[0].parent direction2 = bond2.shortest_vector_relative_to(parent) if bond2.children[0].target != target_object: direction2 *= -1 axis = numpy.cross(direction2, direction1) if numpy.linalg.norm(axis) < 1e-8: axis = random_orthonormal(direction1) angle = compute_angle(direction1, direction2) rotation = Rotation.from_properties(angle, axis, False) primitive.Transform(new, rotation) else: bond1 = None # Tranlsation pos_old = new.children[1].get_frame_relative_to(parent).t pos_new = gl_object.transformation.t translation = Translation(pos_new - pos_old) primitive.Transform(new, translation) if bond1 != None: # bond length old_length = numpy.linalg.norm(direction1) new_length = bonds.get_length( new.children[1].number, bond1.get_neighbor(gl_object).number) translation = Translation(-direction1 / old_length * (new_length - old_length)) primitive.Transform(new, translation) # let the references to the replaced object point to the new object for reference in gl_object.references[::-1]: try: primitive.SetTarget(reference, target_object) except primitive.PrimitiveError: primitive.Delete(reference.parent) # delete the replaced object primitive.Delete(gl_object) if (self.current_object == "Fragment"): # Delete the first atom in the fragment primitive.Delete(new.children[0]) # Unframe the fragment UnframeAbsolute = context.application.plugins.get_action( "UnframeAbsolute") UnframeAbsolute([new])
def compute_transformation(self, connection): #print connection.pairs triangle1 = connection.triangle1 triangle2 = connection.triangle2 triangles = [triangle1, triangle2] #print "BEFORE TRANSFORMING\n" #for triangle in triangles: # #print "-------" # for coordinate in triangle.coordinates: # #print coordinate #print "---------" # *** t1: translation of triangle in geometry2 to origin t1 = Translation(-triangle2.center) #print triangle2.center triangle2.apply_to_coordinates(t1) # also move triangle1 to the origin t_tmp = Translation(-triangle1.center) # was t0 triangle1.apply_to_coordinates(t_tmp) #print "AFTER CENTERING (T1 and T0)" #for triangle in triangles: # #print "-------" # for coordinate in triangle.coordinates: # #print coordinate # *** r2: make the two triangles coplanar #print "NORMALS" #print triangle1.normal #print triangle2.normal rotation_axis = numpy.cross(triangle2.normal, triangle1.normal) if numpy.dot(rotation_axis, rotation_axis) < 1e-8: rotation_axis = random_orthonormal(triangle2.normal) rotation_angle = angle(triangle2.normal, triangle1.normal) #print "R2 %s, %s" % (rotation_angle/numpy.pi*180, rotation_axis) r2 = Rotation.from_properties(rotation_angle, rotation_axis, False) triangle2.apply_to_coordinates(r2) #print "AFTER R2" #for triangle in triangles: # #print "-------" # for coordinate in triangle.coordinates: # #print coordinate # bring both triangles in the x-y plane, by a rotation around an axis # orthogonal to the Z-axis. rotation_axis = numpy.array( [triangle1.normal[1], -triangle1.normal[0], 0.0], float) if numpy.dot(rotation_axis, rotation_axis) < 1e-8: rotation_axis = numpy.array([1.0, 0.0, 0.0], float) cos_angle = triangle1.normal[2] if cos_angle >= 1.0: rotation_angle = 0 elif cos_angle <= -1.0: rotation_angle = numpy.pi else: rotation_angle = numpy.arccos(cos_angle) #print "RT %s, %s" % (rotation_angle/numpy.pi*180, rotation_axis) r_flat = Rotation.from_properties(rotation_angle, rotation_axis, False) triangle1.apply_to_coordinates(r_flat) triangle2.apply_to_coordinates(r_flat) #print "AFTER RT" #for triangle in triangles: # #print "-------" # for coordinate in triangle.coordinates: # #print coordinate # *** r3: second rotation that makes both triangle coinced H = lambda a, b, c, d: a * c + b * d + (a + b) * (c + d) c = (H(triangle1.coordinates[0][0], triangle1.coordinates[1][0], triangle2.coordinates[0][0], triangle2.coordinates[1][0]) + H(triangle1.coordinates[0][1], triangle1.coordinates[1][1], triangle2.coordinates[0][1], triangle2.coordinates[1][1])) s = (H(triangle1.coordinates[0][1], triangle1.coordinates[1][1], triangle2.coordinates[0][0], triangle2.coordinates[1][0]) - H(triangle1.coordinates[0][0], triangle1.coordinates[1][0], triangle2.coordinates[0][1], triangle2.coordinates[1][1])) #if c > s: c, s = -c, -s #print "cos=%f sin=%f" % (c, s) rotation_angle = numpy.arctan2(s, c) #print "R3 %s, %s" % (rotation_angle/numpy.pi*180, triangle1.normal) r3 = Rotation.from_properties(rotation_angle, triangle1.normal, False) r_tmp = Rotation.from_properties(rotation_angle, numpy.array([0, 0, 1], float), False) triangle2.apply_to_coordinates(r_tmp) #print "AFTER R3" #for triangle in triangles: # #print "-------" # for coordinate in triangle.coordinates: # #print coordinate # t4: translate the triangle to the definitive coordinate t4 = Translation(triangle1.center) #print "AFTER T4" #for triangle in triangles: # #print "-------" # for coordinate in triangle.coordinates: # #print coordinate return t4 * r3 * r2 * t1
def replace(self, gl_object): if not gl_object.get_fixed(): new = self.get_new(gl_object.transformation.t) # select a target object, i.e. the one the will be connected with # the bonds/vectors/... of the replaced object if(self.current_object == "Fragment"): # fragments are inserted as frames # take atom with index 1 as target target_object = new.children[1] else: target_object = new # check if all connections to the replaced object are applicable # to the new object. if not, then do not perform the replacement # and return early. for reference in gl_object.references[::-1]: if not reference.check_target(target_object): return # add the new object parent = gl_object.parent primitive.Add(new, parent) if(self.current_object == "Fragment"): # Fix the rotation and translation of the molecular fragment. # Rotation Bond = context.application.plugins.get_node("Bond") if len(gl_object.references) == 1 and isinstance(gl_object.references[0].parent, Bond): bond1 = gl_object.references[0].parent direction1 = bond1.shortest_vector_relative_to(parent) if bond1.children[0].target != gl_object: direction1 *= -1 bond2 = new.children[0].references[0].parent direction2 = bond2.shortest_vector_relative_to(parent) if bond2.children[0].target != target_object: direction2 *= -1 axis = numpy.cross(direction2, direction1) if numpy.linalg.norm(axis) < 1e-8: axis = random_orthonormal(direction1) angle = compute_angle(direction1, direction2) rotation = Rotation.from_properties(angle, axis, False) primitive.Transform(new, rotation) else: bond1 = None # Tranlsation pos_old = new.children[1].get_frame_relative_to(parent).t pos_new = gl_object.transformation.t translation = Translation(pos_new - pos_old) primitive.Transform(new, translation) if bond1 != None: # bond length old_length = numpy.linalg.norm(direction1) new_length = bonds.get_length(new.children[1].number, bond1.get_neighbor(gl_object).number) translation = Translation(-direction1/old_length*(new_length-old_length)) primitive.Transform(new, translation) # let the references to the replaced object point to the new object for reference in gl_object.references[::-1]: try: primitive.SetTarget(reference, target_object) except primitive.PrimitiveError: primitive.Delete(reference.parent) # delete the replaced object primitive.Delete(gl_object) if(self.current_object == "Fragment"): # Delete the first atom in the fragment primitive.Delete(new.children[0]) # Unframe the fragment UnframeAbsolute = context.application.plugins.get_action("UnframeAbsolute") UnframeAbsolute([new])
def compute_transformation(self, connection): # print connection.pairs triangle1 = connection.triangle1 triangle2 = connection.triangle2 triangles = [triangle1, triangle2] # print "BEFORE TRANSFORMING\n" # for triangle in triangles: # #print "-------" # for coordinate in triangle.coordinates: # #print coordinate # print "---------" # *** t1: translation of triangle in geometry2 to origin t1 = Translation(-triangle2.center) # print triangle2.center triangle2.apply_to_coordinates(t1) # also move triangle1 to the origin t_tmp = Translation(-triangle1.center) # was t0 triangle1.apply_to_coordinates(t_tmp) # print "AFTER CENTERING (T1 and T0)" # for triangle in triangles: # #print "-------" # for coordinate in triangle.coordinates: # #print coordinate # *** r2: make the two triangles coplanar # print "NORMALS" # print triangle1.normal # print triangle2.normal rotation_axis = numpy.cross(triangle2.normal, triangle1.normal) if numpy.dot(rotation_axis, rotation_axis) < 1e-8: rotation_axis = random_orthonormal(triangle2.normal) rotation_angle = angle(triangle2.normal, triangle1.normal) # print "R2 %s, %s" % (rotation_angle/numpy.pi*180, rotation_axis) r2 = Rotation.from_properties(rotation_angle, rotation_axis, False) triangle2.apply_to_coordinates(r2) # print "AFTER R2" # for triangle in triangles: # #print "-------" # for coordinate in triangle.coordinates: # #print coordinate # bring both triangles in the x-y plane, by a rotation around an axis # orthogonal to the Z-axis. rotation_axis = numpy.array([triangle1.normal[1], -triangle1.normal[0], 0.0], float) if numpy.dot(rotation_axis, rotation_axis) < 1e-8: rotation_axis = numpy.array([1.0, 0.0, 0.0], float) cos_angle = triangle1.normal[2] if cos_angle >= 1.0: rotation_angle = 0 elif cos_angle <= -1.0: rotation_angle = numpy.pi else: rotation_angle = numpy.arccos(cos_angle) # print "RT %s, %s" % (rotation_angle/numpy.pi*180, rotation_axis) r_flat = Rotation.from_properties(rotation_angle, rotation_axis, False) triangle1.apply_to_coordinates(r_flat) triangle2.apply_to_coordinates(r_flat) # print "AFTER RT" # for triangle in triangles: # #print "-------" # for coordinate in triangle.coordinates: # #print coordinate # *** r3: second rotation that makes both triangle coinced H = lambda a, b, c, d: a * c + b * d + (a + b) * (c + d) c = H( triangle1.coordinates[0][0], triangle1.coordinates[1][0], triangle2.coordinates[0][0], triangle2.coordinates[1][0], ) + H( triangle1.coordinates[0][1], triangle1.coordinates[1][1], triangle2.coordinates[0][1], triangle2.coordinates[1][1], ) s = H( triangle1.coordinates[0][1], triangle1.coordinates[1][1], triangle2.coordinates[0][0], triangle2.coordinates[1][0], ) - H( triangle1.coordinates[0][0], triangle1.coordinates[1][0], triangle2.coordinates[0][1], triangle2.coordinates[1][1], ) # if c > s: c, s = -c, -s # print "cos=%f sin=%f" % (c, s) rotation_angle = numpy.arctan2(s, c) # print "R3 %s, %s" % (rotation_angle/numpy.pi*180, triangle1.normal) r3 = Rotation.from_properties(rotation_angle, triangle1.normal, False) r_tmp = Rotation.from_properties(rotation_angle, numpy.array([0, 0, 1], float), False) triangle2.apply_to_coordinates(r_tmp) # print "AFTER R3" # for triangle in triangles: # #print "-------" # for coordinate in triangle.coordinates: # #print coordinate # t4: translate the triangle to the definitive coordinate t4 = Translation(triangle1.center) # print "AFTER T4" # for triangle in triangles: # #print "-------" # for coordinate in triangle.coordinates: # #print coordinate return t4 * r3 * r2 * t1
def add_hydrogens(atom): existing_bonds = list(atom.iter_bonds()) num_bonds = len(existing_bonds) bond_length = bonds.get_length(atom.number, 1, BOND_SINGLE) if num_bonds == 0: t = atom.transformation.t + numpy.array([0,bond_length,0]) H = Atom(name="auto H", number=1, transformation=Translation(t)) primitive.Add(H, atom.parent) bond = Bond(name="aut H bond", targets=[atom, H]) primitive.Add(bond, atom.parent) existing_bonds.append(bond) num_bonds = 1 used_valence = 0 oposite_direction = numpy.zeros(3, float) for bond in existing_bonds: shortest_vector = bond.shortest_vector_relative_to(atom.parent) if bond.children[1].target == atom: shortest_vector *= -1 oposite_direction -= shortest_vector if bond.bond_type == BOND_SINGLE: used_valence += 1 elif bond.bond_type == BOND_DOUBLE: used_valence += 2 elif bond.bond_type == BOND_TRIPLE: used_valence += 3 oposite_direction /= numpy.linalg.norm(oposite_direction) num_hydrogens = valence_el(atom.number) - 2*lone_pairs(atom.number) - used_valence if num_hydrogens <= 0: return hybride_count = num_hydrogens + lone_pairs(atom.number) + num_bonds - (used_valence - num_bonds) num_sites = num_hydrogens + lone_pairs(atom.number) rotation = Rotation.from_properties(2*numpy.pi / float(num_sites), oposite_direction, False) opening_key = (hybride_count, num_sites) opening_angle = self.opening_angles.get(opening_key) if opening_angle is None: return if num_bonds == 1: first_bond = existing_bonds[0] other_atom = first_bond.children[0].target if other_atom == atom: other_atom = first_bond.children[1].target other_bonds = [bond for bond in other_atom.iter_bonds() if bond != first_bond] if len(other_bonds) > 0: normal = other_bonds[0].shortest_vector_relative_to(atom.parent) normal -= numpy.dot(normal, oposite_direction) * oposite_direction normal /= numpy.linalg.norm(normal) if other_bonds[0].children[0].target == other_atom: normal *= -1 else: normal = random_orthonormal(oposite_direction) elif num_bonds == 2: normal = numpy.cross(oposite_direction, existing_bonds[0].shortest_vector_relative_to(atom.parent)) normal /= numpy.linalg.norm(normal) elif num_bonds == 3: normal = random_orthonormal(oposite_direction) else: return h_pos = bond_length*(oposite_direction*numpy.cos(opening_angle) + normal*numpy.sin(opening_angle)) for i in range(num_hydrogens): t = atom.transformation.t + h_pos H = Atom(name="auto H", number=1, transformation=Translation(t)) primitive.Add(H, atom.parent) bond = Bond(name="aut H bond", targets=[atom, H]) primitive.Add(bond, atom.parent) h_pos = rotation * h_pos