Example #1
0
 def find_place( self, a, distance, added_order=1):
   """tries to find accurate place for next atom around atom 'id',
   returns x,y and list of ids of 'items' found there for overlap, those atoms are not bound to id"""
   ids_bonds = a.neighbors
   if len( ids_bonds) == 0:
     x = a.x + cos( pi/6) *distance
     y = a.y - sin( pi/6) *distance
   elif len( ids_bonds) == 1:
     neigh = ids_bonds[0]
     if a.neighbor_edges[0].order != 3 and added_order != 3:
       # we add a normal bond to atom with one normal bond
       if a == self._last_used_atom or len( neigh.neighbors) != 2:
         # the user has either deleted the last added bond and wants it to be on the other side
         # or it is simply impossible to define a transoid configuration
         self.sign = -self.sign
         x = a.x + cos( self.get_angle( a, ids_bonds[0]) +self.sign*2*pi/3) *distance
         y = a.y + sin( self.get_angle( a, ids_bonds[0]) +self.sign*2*pi/3) *distance
       else:
         # we would add the new bond transoid
         neighs2 = neigh.neighbors
         neigh2 = (neighs2[0] == a) and neighs2[1] or neighs2[0]
         x = a.x + cos( self.get_angle( a, neigh) +self.sign*2*pi/3) *distance
         y = a.y + sin( self.get_angle( a, neigh) +self.sign*2*pi/3) *distance
         side = geometry.on_which_side_is_point( (neigh.x,neigh.y,a.x,a.y), (x,y))
         if side == geometry.on_which_side_is_point(  (neigh.x,neigh.y,a.x,a.y), (neigh2.x,neigh2.y)):
           self.sign = -self.sign
           x = a.x + cos( self.get_angle( a, neigh) +self.sign*2*pi/3) *distance
           y = a.y + sin( self.get_angle( a, neigh) +self.sign*2*pi/3) *distance
         self._last_used_atom = a
     else:
       x = a.x + cos( self.get_angle( a, ids_bonds[0]) + pi) *distance
       y = a.y + sin( self.get_angle( a, ids_bonds[0]) + pi) *distance
   else:
     x, y = self.find_least_crowded_place_around_atom( a, range=distance)
   return x, y
Example #2
0
 def _draw_second_line( self, coords):
   my_x1, my_y1 = self.atom1.get_xy()
   my_x2, my_y2 = self.atom2.get_xy()
   my_coords = (my_x1,my_y1,my_x2,my_y2)
   x, y, x0, y0 = coords
   # shortening of the second bond
   dx = x-x0
   dy = y-y0
   if self.center:
     _k = 0
   else:
     _k = (1-self.double_length_ratio)/2
   x, y, x0, y0 = x-_k*dx, y-_k*dy, x0+_k*dx, y0+_k*dy
   # shift according to the bonds arround
   side = geometry.on_which_side_is_point( my_coords, (x,y))
   for atom in (self.atom1,self.atom2):
     second_atom = atom is self.atom1 and self.atom2 or self.atom1
     neighs = [n for n in atom.neighbors if geometry.on_which_side_is_point( my_coords, n.get_xy())==side and n is not second_atom]
     for n in neighs:
       dist2 = _k*geometry.point_distance(*my_coords)*geometry.on_which_side_is_point((atom.x, atom.y, n.x, n.y), (second_atom.x, second_atom.y))
       xn1, yn1, xn2, yn2 = geometry.find_parallel( atom.x, atom.y, n.x, n.y, dist2)
       xp,yp,parallel,online = geometry.intersection_of_two_lines( x,y,x0,y0,xn1,yn1,xn2,yn2)
       if not parallel:
         if not geometry.is_point_beween_points_of_line( (x,y,x0,y0),(xp,yp)):
           # only shorten the line - do not elongate it
           continue
         if geometry.point_distance( atom.x,atom.y,x,y) < geometry.point_distance( atom.x,atom.y,x0,y0):
           x,y = xp, yp
         else:
           x0,y0 = xp, yp
       else:
         # parallel
         pass
   return [self._create_line_with_transform( (x, y, x0, y0), width=self.line_width, fill=self.line_color)]
Example #3
0
 def _draw_second_line( self, coords):
   my_x1, my_y1 = self.atom1.get_xy()
   my_x2, my_y2 = self.atom2.get_xy()
   my_coords = (my_x1,my_y1,my_x2,my_y2)
   x, y, x0, y0 = coords
   # shortening of the second bond
   dx = x-x0
   dy = y-y0
   if self.center:
     _k = 0
   else:
     _k = (1-self.double_length_ratio)/2
   x, y, x0, y0 = x-_k*dx, y-_k*dy, x0+_k*dx, y0+_k*dy
   # shift according to the bonds arround
   side = geometry.on_which_side_is_point( my_coords, (x,y))
   for atom in (self.atom1,self.atom2):
     second_atom = atom is self.atom1 and self.atom2 or self.atom1
     neighs = [n for n in atom.neighbors if geometry.on_which_side_is_point( my_coords, n.get_xy())==side and n is not second_atom]
     for n in neighs:
       dist2 = _k*geometry.point_distance(*my_coords)*geometry.on_which_side_is_point((atom.x, atom.y, n.x, n.y), (second_atom.x, second_atom.y))
       xn1, yn1, xn2, yn2 = geometry.find_parallel( atom.x, atom.y, n.x, n.y, dist2)
       xp,yp,parallel,online = geometry.intersection_of_two_lines( x,y,x0,y0,xn1,yn1,xn2,yn2)
       if not parallel:
         if not geometry.is_point_beween_points_of_line( (x,y,x0,y0),(xp,yp)):
           # only shorten the line - do not elongate it
           continue
         if geometry.point_distance( atom.x,atom.y,x,y) < geometry.point_distance( atom.x,atom.y,x0,y0):
           x,y = xp, yp
         else:
           x0,y0 = xp, yp
       else:
         # parallel
         pass
   return [self._create_line_with_transform( (x, y, x0, y0), width=self.line_width, fill=self.line_color)]
Example #4
0
 def find_place(self, a, distance, added_order=1):
     """tries to find accurate place for next atom around atom 'id',
 returns x,y and list of ids of 'items' found there for overlap, those atoms are not bound to id"""
     ids_bonds = a.neighbors
     if len(ids_bonds) == 0:
         x = a.x + cos(pi / 6) * distance
         y = a.y - sin(pi / 6) * distance
     elif len(ids_bonds) == 1:
         neigh = ids_bonds[0]
         if a.neighbor_edges[0].order != 3 and added_order != 3:
             # we add a normal bond to atom with one normal bond
             if a == self._last_used_atom or len(neigh.neighbors) != 2:
                 # the user has either deleted the last added bond and wants it to be on the other side
                 # or it is simply impossible to define a transoid configuration
                 self.sign = -self.sign
                 x = a.x + cos(
                     self.get_angle(a, ids_bonds[0]) +
                     self.sign * 2 * pi / 3) * distance
                 y = a.y + sin(
                     self.get_angle(a, ids_bonds[0]) +
                     self.sign * 2 * pi / 3) * distance
             else:
                 # we would add the new bond transoid
                 neighs2 = neigh.neighbors
                 neigh2 = (neighs2[0] == a) and neighs2[1] or neighs2[0]
                 x = a.x + cos(
                     self.get_angle(a, neigh) +
                     self.sign * 2 * pi / 3) * distance
                 y = a.y + sin(
                     self.get_angle(a, neigh) +
                     self.sign * 2 * pi / 3) * distance
                 side = geometry.on_which_side_is_point(
                     (neigh.x, neigh.y, a.x, a.y), (x, y))
                 if side == geometry.on_which_side_is_point(
                     (neigh.x, neigh.y, a.x, a.y), (neigh2.x, neigh2.y)):
                     self.sign = -self.sign
                     x = a.x + cos(
                         self.get_angle(a, neigh) +
                         self.sign * 2 * pi / 3) * distance
                     y = a.y + sin(
                         self.get_angle(a, neigh) +
                         self.sign * 2 * pi / 3) * distance
                 self._last_used_atom = a
         else:
             x = a.x + cos(self.get_angle(a, ids_bonds[0]) + pi) * distance
             y = a.y + sin(self.get_angle(a, ids_bonds[0]) + pi) * distance
     else:
         x, y = self.find_least_crowded_place_around_atom(a, range=distance)
     return x, y
Example #5
0
 def mark_template_bond( self, b):
   if b in self.edges:
     atms = b.atom1.neighbors + b.atom2.neighbors
     atms = misc.difference( atms, [b.atom1, b.atom2])
     coords = [a.get_xy() for a in atms]
     line = b.atom1.get_xy() + b.atom2.get_xy()
     if sum(geometry.on_which_side_is_point(line, xy) for xy in coords) > 0:
       self.t_bond_first = b.atom1
       self.t_bond_second = b.atom2
     else:
       self.t_bond_first = b.atom2
       self.t_bond_second = b.atom1
   else:
     raise ValueError("Submitted bond does not belong to this molecule.")
Example #6
0
 def mark_template_bond(self, b):
     if b in self.edges:
         atms = b.atom1.neighbors + b.atom2.neighbors
         atms = misc.difference(atms, [b.atom1, b.atom2])
         coords = [a.get_xy() for a in atms]
         line = b.atom1.get_xy() + b.atom2.get_xy()
         if sum(geometry.on_which_side_is_point(line, xy)
                for xy in coords) > 0:
             self.t_bond_first = b.atom1
             self.t_bond_second = b.atom2
         else:
             self.t_bond_first = b.atom2
             self.t_bond_second = b.atom1
     else:
         raise ValueError(
             "Submitted bond does not belong to this molecule.")
Example #7
0
 def transform( self, tr):
   if not self.item:
     return
   for i in [self.item] + self.second + self.third + self.items:
     coords = self.paper.coords( i)
     tr_coords = tr.transform_xy_flat_list( coords)
     self.paper.coords( i, tuple( tr_coords))
   if self.selector:
     self.unselect()
     self.select()
   # we need to check if the sign of double bond width has not changed
   # this happens during 3d rotation
   if self.order == 2 and not self.center:
     line = list( self.atom1.get_xy())
     line += self.atom2.get_xy()
     x, y = self.paper.coords( self.second[0])[0:2]
     sign = geometry.on_which_side_is_point( line, (x,y))
     if sign * self.bond_width < 0:
       self.bond_width *= -1
Example #8
0
 def transform( self, tr):
   if not self.item:
     return
   for i in [self.item] + self.second + self.third + self.items:
     coords = self.paper.coords( i)
     tr_coords = tr.transform_xy_flat_list( coords)
     self.paper.coords( i, tuple( tr_coords))
   if self.selector:
     self.unselect()
     self.select()
   # we need to check if the sign of double bond width has not changed
   # this happens during 3d rotation
   if self.order == 2 and not self.center:
     line = list( self.atom1.get_xy())
     line += self.atom2.get_xy()
     x, y = self.paper.coords( self.second[0])[0:2]
     sign = geometry.on_which_side_is_point( line, (x,y))
     if sign * self.bond_width < 0:
       self.bond_width *= -1
Example #9
0
 def _compute_sign_and_center( self):
   """returns tuple of (sign, center) where sign is the default sign of the self.bond_width"""
   # check if we need to transform 3D before computation
   transform = None
   for n in self.atom1.neighbors + self.atom2.neighbors:
     # self.atom1 and self.atom2 are in this list as well
     if n.z != 0:
       # engage 3d transform prior to detection of where to draw
       transform = self._get_3dtransform_for_drawing()
       break
   if transform:
     for n in self.atom1.neighbors + self.atom2.neighbors:
       n.transform( transform)
   # /end of check
   line = self.atom1.get_xy() + self.atom2.get_xy()
   atms = self.atom1.neighbors + self.atom2.neighbors
   atms = misc.difference( atms, [self.atom1, self.atom2])
   coords = [a.get_xy() for a in atms]
   # searching for circles
   circles = 0
   for ring in self.molecule.get_smallest_independent_cycles_dangerous_and_cached():
     if self.atom1 in ring and self.atom2 in ring:
       on_which_side = lambda xy: geometry.on_which_side_is_point( line, xy)
       circles += sum(map(on_which_side, [a.get_xy() for a in ring if a not in self.atoms]))
   if circles:
     side = circles
   else:
     sides = [geometry.on_which_side_is_point( line, xy, threshold=0.1) for xy in coords]
     side = sum(sides)
   # on which side to put the second line
   if side == 0 and (len(self.atom1.neighbors) == 1 or
                     len(self.atom2.neighbors) == 1):
     # maybe we should center, but this is usefull only when one of the atoms has no other substitution
     ret = (1 ,1)
   else:
     ret = None
     if not circles:
       # we center when both atoms have visible symbol and are not in circle
       if self.atom1.show and self.atom2.show:
         ret = (1, 1)
       # recompute side with weighting of atom types
       else:
         for i in range( len( sides)):
           if sides[i] and atms[i].__class__.__name__ == "atom":
             if atms[i].symbol == 'H':
               sides[i] *= 0.1 # this discriminates H
             elif atms[i].symbol != 'C':
               sides[i] *= 0.2 # this makes "non C" less then C but more then H
           side = sum(sides)
     if not ret:
       if side < 0:
         ret = (-1, 0)
       else:
         ret = (1, 0)
   # transform back if necessary
   if transform:
     inv = transform.get_inverse()
     for n in self.atom1.neighbors + self.atom2.neighbors:
       n.transform( inv)
   # /end of back transform
   return ret
Example #10
0
 def _compute_sign_and_center( self):
   """returns tuple of (sign, center) where sign is the default sign of the self.bond_width"""
   # check if we need to transform 3D before computation
   transform = None
   for n in self.atom1.neighbors + self.atom2.neighbors:
     # self.atom1 and self.atom2 are in this list as well
     if n.z != 0:
       # engage 3d transform prior to detection of where to draw
       transform = self._get_3dtransform_for_drawing()
       break
   if transform:
     for n in self.atom1.neighbors + self.atom2.neighbors:
       n.transform( transform)
   # /end of check
   line = self.atom1.get_xy() + self.atom2.get_xy()
   atms = self.atom1.neighbors + self.atom2.neighbors
   atms = misc.difference( atms, [self.atom1, self.atom2])
   coords = [a.get_xy() for a in atms]
   # searching for circles
   circles = 0
   for ring in self.molecule.get_smallest_independent_cycles_dangerous_and_cached():
     if self.atom1 in ring and self.atom2 in ring:
       on_which_side = lambda xy: geometry.on_which_side_is_point( line, xy)
       circles += sum(map(on_which_side, [a.get_xy() for a in ring if a not in self.atoms]))
   if circles:
     side = circles
   else:
     sides = [geometry.on_which_side_is_point( line, xy, threshold=0.1) for xy in coords]
     side = sum(sides)
   # on which side to put the second line
   if side == 0 and (len(self.atom1.neighbors) == 1 or
                     len(self.atom2.neighbors) == 1):
     # maybe we should center, but this is usefull only when one of the atoms has no other substitution
     ret = (1 ,1)
   else:
     ret = None
     if not circles:
       # we center when both atoms have visible symbol and are not in circle
       if self.atom1.show and self.atom2.show:
         ret = (1, 1)
       # recompute side with weighting of atom types
       else:
         for i in range( len( sides)):
           if sides[i] and atms[i].__class__.__name__ == "atom":
             if atms[i].symbol == 'H':
               sides[i] *= 0.1 # this discriminates H
             elif atms[i].symbol != 'C':
               sides[i] *= 0.2 # this makes "non C" less then C but more then H
           side = sum(sides)
     if ret is None:
       if side < 0:
         ret = (-1, 0)
       else:
         ret = (1, 0)
   # transform back if necessary
   if transform:
     inv = transform.get_inverse()
     for n in self.atom1.neighbors + self.atom2.neighbors:
       n.transform( inv)
   # /end of back transform
   return ret