Exemple #1
0
 def _is_there_place( self, atom, x, y):
   x1, y1 = atom.x, atom.y
   angle1 = geometry.clockwise_angle_from_east( x-x1, y-y1)
   for n in atom.neighbors:
     angle = geometry.clockwise_angle_from_east( n.x-x1, n.y-y1)
     if abs( angle - angle1) < 0.3:
       return False
   return True
Exemple #2
0
 def _is_there_place(self, atom, x, y):
     x1, y1 = atom.x, atom.y
     angle1 = geometry.clockwise_angle_from_east(x - x1, y - y1)
     for n in atom.neighbors:
         angle = geometry.clockwise_angle_from_east(n.x - x1, n.y - y1)
         if abs(angle - angle1) < 0.3:
             return False
     return True
Exemple #3
0
 def _process_simply_anelated_ring( self, ring, base):
   out = []
   inter = [v for v in ring if v.x != None and v.y != None]
   if len( inter) == 1:
     # rings are connected via one atom
     v = inter.pop() # the atom of concatenation
     ring = self.mol.sort_vertices_in_path( ring, start_from=v)
     base_neighs = [a for a in v.get_neighbors() if a in base]
     if len( base_neighs) < 2:
       raise "this should not happen"
     d1 = base_neighs[0] 
     d2 = base_neighs[1]
     ca1 = geometry.clockwise_angle_from_east( v.x-d1.x, v.y-d1.y)
     ca2 = geometry.clockwise_angle_from_east( v.x-d2.x, v.y-d2.y)
     ca = (ca1+ca2)/2
     if abs( ca1-ca2) < pi:
       ca += -pi/2
     else:
       ca += pi/2
     size = len( ring)
     da = deg_to_rad(180 -180.0*(size-2)/size)
     gcoords = gen_angle_stream( da, start_from=ca + da/2)
     ring.remove( v)
     # here we generate the coords
     self.apply_gen_to_atoms( gcoords, ring, v)
     ring.append( v)
     out += ring
   elif len( inter) == 2:
     # there are two atoms common to the rings
     v1, v2 = inter # the atoms of concatenation
     ring = self.mol.sort_vertices_in_path( ring, start_from=v1)
     ring.remove( v1)
     ring.remove( v2)
     if not v1 in ring[0].get_neighbors():
       v1, v2 = v2, v1
     side = sum( [geometry.on_which_side_is_point((v1.x,v1.y,v2.x,v2.y),(v.x,v.y)) for v in base])
     if not side:
       warnings.warn( "this should not happen")
     ca = geometry.clockwise_angle_from_east( v1.x-v2.x, v1.y-v2.y)
     size = len( ring)+2
     da = deg_to_rad(180 -180.0*(size-2)/size)
     if side > 0:
       da = -da
     gcoords = gen_angle_stream( da, start_from=ca+da)
     self.apply_gen_to_atoms( gcoords, ring, v1)
     ring.append( v1)
     ring.append( v2)
     out += ring
   else:
     # there are more than 2 atoms common
     if len( ring) == len( base):
       out += self._process_multi_anelated_ring( ring, angle_shift=15)
       #raise( "i don't how to handle this yet")
     else:
       out += self._process_multi_anelated_ring( ring)
   return out
Exemple #4
0
  def get_angle_gradient2( self, opt_angle, refv, v1, v2):
    ang1 = geometry.clockwise_angle_from_east( v1.x-refv.x, v1.y-refv.y)
    ang2 = geometry.clockwise_angle_from_east( v2.x-refv.x, v2.y-refv.y)
    ang = ang1 - ang2
    sign = -geometry.on_which_side_is_point( (refv.x, refv.y, v1.x, v1.y), (v2.x, v2.y))
    
    while ang < 0:
      ang += 2*pi
    if ang > pi:
      ang = 2*pi - ang
      sign *= -1

    dang = (ang - opt_angle) / 2

    gx1 = (cos( ang1 - sign*dang) - cos( ang1)) * sqrt( (refv.x-v1.x)**2 + (refv.y-v1.y)**2) #self.bond_length #(v1.x-refv.x)
    gy1 = (sin( ang1 - sign*dang) - sin( ang1)) * sqrt( (refv.x-v1.x)**2 + (refv.y-v1.y)**2) #self.bond_length #(v1.y-refv.y)

    gx2 = (cos( ang2 + sign*dang) - cos( ang2)) * sqrt( (refv.x-v2.x)**2 + (refv.y-v2.y)**2) #self.bond_length #(v2.x-refv.x)
    gy2 = (sin( ang2 + sign*dang) - sin( ang2)) * sqrt( (refv.x-v2.x)**2 + (refv.y-v2.y)**2) #self.bond_length #(v2.y-refv.y)


    # control
    ang1 = geometry.clockwise_angle_from_east( v1.x-refv.x+gx1, v1.y-refv.y+gy1)
    ang2 = geometry.clockwise_angle_from_east( v2.x-refv.x+gx2, v2.y-refv.y+gy2)
    ang = ang1 - ang2
    sign = geometry.on_which_side_is_point( (refv.x, refv.y, v1.x, v1.y), (v2.x, v2.y))
    
    while ang < 0:
      ang += 2*pi
      #sign *= -1
    if ang > pi:
      ang = 2*pi - ang
      #sign *= -1

    dang2 = (ang - opt_angle) / 2

    if abs( dang2) > abs( dang):
      print "f**k", rad_to_deg( ang1), rad_to_deg( ang2), rad_to_deg( dang)
    else:
      #rint "good", rad_to_deg( ang1), rad_to_deg( ang2), rad_to_deg( dang)
      pass

    return gx1, gy1, gx2, gy2
Exemple #5
0
 def _find_place_around_atom( self, atom):
   x, y = atom.x, atom.y
   coords = [(a.x,a.y) for a in atom.neighbors]
   # now we can compare the angles
   angles = [geometry.clockwise_angle_from_east( x1-x, y1-y) for x1,y1 in coords]
   angles.append( 2*math.pi + min( angles))
   angles.sort()
   angles.reverse()
   diffs = misc.list_difference( angles)
   i = diffs.index( max( diffs))
   angle = (angles[i] +angles[i+1]) / 2
   return angle
Exemple #6
0
 def _process_multi_anelated_ring( self, ring, angle_shift=0):
   out = []
   to_go = [v for v in ring if v.x == None or v.y == None]
   if not to_go:
     # it was all already done
     return []
   back = [v for v in ring if v.x != None and v.y != None]
   sorted_back = self.mol.sort_vertices_in_path( back)
   if not sorted_back:
     # the already set atoms are not in one path - we have to process it "per partes"
     # it should not happen with the construction method we use
     raise( "i am not able to handle this, it should normaly not happen. please send me the input.")
   else:
     v1 = sorted_back[0]
     v2 = sorted_back[-1]
     v3 = sorted_back[1]
     to_go = self.mol.sort_vertices_in_path( to_go)
     if v1 not in to_go[0].get_neighbors():
       v1, v2 = v2, v1
     blocked_angle = sum_of_ring_internal_angles( len( back))
     overall_angle = sum_of_ring_internal_angles( len( ring))
     da = optimal_ring_iternal_angle( len( ring))  # internal angle
     # if there are 2 rings of same size inside each other, we need to use the angle_shift
     if angle_shift:
       da += 2*angle_shift/(len( to_go))
     ca = deg_to_rad( 180-(overall_angle - blocked_angle - len( to_go) * da + angle_shift)/2)  # connection angle
     side = sum( [geometry.on_which_side_is_point( (v1.x,v1.y,v2.x,v2.y),(v.x,v.y)) for v in back if v != v1 and v != v2])
     # we need to make sure that the ring is drawn on the right side
     if side > 0:
       ca = -ca
     ca += geometry.clockwise_angle_from_east( v1.x-v2.x, v1.y-v2.y)
     da = 180-da  # for drawing we use external angle
     # we must ensure that the ring will progress towards the second end
     if geometry.on_which_side_is_point( (v1.x,v1.y,v3.x,v3.y),(v2.x,v2.y)) < 0:
       da = -da
     # dry run to see where we get
     gcoords = gen_angle_stream( deg_to_rad( da), start_from= ca)
     x, y = v1.x, v1.y
     for i in range( len( to_go) +1):
       a = gcoords.next()
       x += self.bond_length*cos( a)
       y += self.bond_length*sin( a)
     # end of dry run, we can scale the bond_length now
     length = geometry.line_length( (v1.x,v1.y,v2.x,v2.y))
     real_length = geometry.line_length( (v1.x,v1.y,x,y))
     bl = self.bond_length * length / real_length
     gcoords = gen_angle_stream( deg_to_rad( da), start_from= ca)
     # and here we go
     self.apply_gen_to_atoms( gcoords, to_go, v1, bond_length=bl)
     out += to_go
   return out
Exemple #7
0
 def _find_place_around_atom(self, atom):
     x, y = atom.x, atom.y
     coords = [(a.x, a.y) for a in atom.neighbors]
     # now we can compare the angles
     angles = [
         geometry.clockwise_angle_from_east(x1 - x, y1 - y)
         for x1, y1 in coords
     ]
     angles.append(2 * math.pi + min(angles))
     angles.sort()
     angles.reverse()
     diffs = misc.list_difference(angles)
     i = diffs.index(max(diffs))
     angle = (angles[i] + angles[i + 1]) / 2
     return angle
Exemple #8
0
 def _continue_with_the_coords( self, mol, processed=[]):
   """processes the atoms in circles around the backbone (processed) until all is done"""
   while processed:
     new_processed = []
     for v in processed:
       if len( [o for o in self.mol.vertices if o.x == None]) == 0:
         # its all done
         return
       # look if v is part of a ring
       ring = None
       for r in self.rings:
         if v in r:
           ring = r
           break
       if not ring:
         # v is not in a ring - we can continue
         new_processed += self.process_atom_neigbors( v)
       else:
         # v is in ring so we process the ring
         if len( processed) > 1 and mol.defines_connected_subgraph_v( processed) and set( processed) <= ring:
           new_processed += self.process_all_anelated_rings( processed)
         else:
           self.rings.remove( ring)
           ring = mol.sort_vertices_in_path( ring, start_from=v)
           ring.remove( v)
           d = [a for a in v.get_neighbors() if a.x != None and a.y != None][0] # should always work
           ca = geometry.clockwise_angle_from_east( v.x-d.x, v.y-d.y)
           size = len( ring)+1
           da = deg_to_rad( 180 -180*(size-2)/size)
           gcoords = gen_angle_stream( da, start_from=ca-pi/2+da/2)
           # here we generate the coords
           self.apply_gen_to_atoms( gcoords, ring, v)
           ring.append( v)
           new_processed += ring
           new_processed += self.process_all_anelated_rings( ring)
     processed = new_processed
Exemple #9
0
 def process_atom_neigbors( self, v):
   def get_angle_at_side( v, d, d2, relation, attach_angle):
     if attach_angle == 180:
       # shortcut
       return attach_angle
     side = geometry.on_which_side_is_point( (d.x,d.y,v.x,v.y), (d2.x,d2.y))
     an = angle + deg_to_rad( attach_angle)
     x = v.x + self.bond_length*cos( an)
     y = v.y + self.bond_length*sin( an)
     if relation*side == geometry.on_which_side_is_point( (d.x,d.y,v.x,v.y), (x,y)):
       return attach_angle
     else:
       return -attach_angle
     
   to_go = [a for a in v.get_neighbors() if a.x == None or a.y == None]
   done = [a for a in v.get_neighbors() if a not in to_go]
   if len( done) == 1 and (len( to_go) == 1 or len( to_go) == 2 and [1 for _t in to_go if _t in self.stereo]):
     # only simple non-branched chain or branched with stereo
     d = done[0]
     if len( to_go) == 1:
       t = to_go[0]
     else:
       t = [_t for _t in to_go if _t in self.stereo][0]
     # decide angle
     angle_to_add = 120
     bond = v.get_edge_leading_to( t)
     # triple bonds
     if 3 in [_e.order for _e in v.get_neighbor_edges()]:
       angle_to_add = 180
     # cumulated double bonds
     if bond.order == 2:
       _b = v.get_edge_leading_to( d)
       if _b.order == 2:
         angle_to_add = 180
     angle = geometry.clockwise_angle_from_east( d.x-v.x, d.y-v.y)
     dns = d.get_neighbors()
     placed = False
     # stereochemistry (E/Z)
     if t in self.stereo:
       ss = [st for st in self.stereo[t] if not None in st.get_other_end( t).coords[:2]]
       if ss:
         st = ss[0] # we choose the first one if more are present
         d2 = st.get_other_end( t)
         # other is processed, we need to adapt
         relation = st.value == st.OPPOSITE_SIDE and -1 or 1
         angle_to_add = get_angle_at_side( v, d, d2, relation, angle_to_add)
         placed = True
     if not placed and len( dns) == 2:
       # to support the all trans of simple chains without stereochemistry
       d2 = (dns[0] == v) and dns[1] or dns[0]
       if d2.x != None and d2.y != None:
         angle_to_add = get_angle_at_side( v, d, d2, -1, angle_to_add)
     an = angle + deg_to_rad( angle_to_add)
     t.x = v.x + self.bond_length*cos( an)
     t.y = v.y + self.bond_length*sin( an)
     if len( to_go) > 1:
       self.process_atom_neigbors( v)
   else:
     # branched chain
     angles = [geometry.clockwise_angle_from_east( at.x-v.x, at.y-v.y) for at in done]
     angles.append( 2*pi + min( angles))
     angles.sort()
     angles.reverse()
     diffs = misc.list_difference( angles)
     i = diffs.index( max( diffs))
     angle = (angles[i] -angles[i+1]) / (len( to_go)+1)
     gcoords = gen_coords_from_stream( gen_angle_stream( angle, start_from=angles[i+1]+angle),
                                       length = self.bond_length)
     for a in to_go:
       dx, dy = gcoords.next()
       a.x = v.x + dx
       a.y = v.y + dy
   return to_go