Exemplo n.º 1
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.")
Exemplo n.º 2
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.")
Exemplo n.º 3
0
    def localize_fake_aromatic_bonds(self):
        to_go = [b for b in self.bonds if b.order == 4]

        processed = []
        for b in to_go:
            if not min([a.free_valency for a in b.vertices]):
                b.order = 1
                processed.append(b)
        to_go = misc.difference(to_go, processed)

        while to_go:
            # find the right bond
            b = None
            for bo in to_go:
                bs1, bs2 = bo.get_neighbor_edges2()
                if not bs1 or len( [e for e in bs1 if e.order == 1]) > 0 and len( [e for e in bs1 if e.order == 2]) == 0 \
                   or not bs2 or len( [e for e in bs2 if e.order == 1]) > 0 and len( [e for e in bs2 if e.order == 2]) == 0:
                    b = bo
                    break
                # new start for iteration
            if not b:
                for bo in self.edges:
                    if not [
                            e for e in bo.get_neighbor_edges() if e.order != 4
                    ]:
                        b = bo
                        break
            if not b:
                b = to_go.pop(0)
            # the code itself
            b.order = 2
            b.aromatic = 0
            for bo in b.get_neighbor_edges():
                if bo.order == 4:
                    bo.order = 1
                    bo.aromatic = 0
            # next turn
            to_go = [b for b in self.bonds if b.order == 4]
Exemplo n.º 4
0
  def localize_fake_aromatic_bonds( self):
    to_go = [b for b in self.bonds if b.order == 4]

    processed = []
    for b in to_go:
      if not min( [a.free_valency for a in b.vertices]):
        b.order = 1
        processed.append( b)
    to_go = misc.difference( to_go, processed)

    while to_go:
      # find the right bond
      b = None
      for bo in to_go:
        bs1, bs2 = bo.get_neighbor_edges2()
        if not bs1 or len( [e for e in bs1 if e.order == 1]) > 0 and len( [e for e in bs1 if e.order == 2]) == 0 \
           or not bs2 or len( [e for e in bs2 if e.order == 1]) > 0 and len( [e for e in bs2 if e.order == 2]) == 0:
          b = bo
          break
        # new start for iteration
      if not b:
        for bo in self.edges:
          if not [e for e in bo.neighbor_edges if e.order != 4]:
            b = bo
            break
      if not b:
        b = to_go.pop(0)
      # the code itself
      b.order = 2
      b.aromatic = 0
      for bo in b.neighbor_edges:
        if bo.order == 4:
          bo.order = 1
          bo.aromatic = 0
      # next turn
      to_go = [b for b in self.bonds if b.order == 4]
Exemplo n.º 5
0
    def set_state(self, previous):
        """sets the system to the recorded state (update is done only where necessary,
    not changed values are not touched)."""
        # we need to know about deleted bonds before we try to redraw them (when updating atom)
        deleted = misc.difference(self.objects, previous.objects)
        added = misc.difference(previous.objects, self.objects)
        to_redraw = set()
        ## CHANGED OBJECTS
        i = 0
        for o in self.objects:
            changed = 0
            for a in o.meta__undo_fake:
                # fakes serve only to force redraw in some cases however do not perform any undo
                if self.records[i][a] != getattr(o, a):
                    changed = 1
            for a in o.meta__undo_simple:
                if self.records[i][a] != o.__dict__[a]:
                    o.__dict__[a] = self.records[i][a]
                    if a != 'molecule':  # this jumps a little from the clean, meta-driven design, however saves much time
                        changed = 1
            for a in o.meta__undo_copy:
                if self.records[i][a] != o.__dict__[a]:
                    o.__dict__[a] = copy.copy(self.records[i][a])
                    changed = 1
                    # this part is not meta driven, I have to rewrite it one day
                    if a == 'bonds':
                        o.edges = o.bonds
                    elif a == 'atoms':
                        o.vertices = o.atoms
                    # / end of the shitty patch
            for a in o.meta__undo_properties:
                if hasattr(o, a):
                    if self.records[i][a] != getattr(o, a):
                        setattr(o, a, self.records[i][a])
                        changed = 1

            if changed:
                to_redraw.add(o)
                # some hacks needed to ensure complete redraw
                if o.object_type == 'atom':
                    neigh_edges = set([
                        b for b in o.neighbor_edges
                        if b not in deleted and b not in added
                    ])
                    to_redraw |= neigh_edges
                    # neighboring edges of the atoms edges - needed because of new bond drawing code
                    # that takes neighboring edges into account
                    neigh_edges2 = set()
                    for e in neigh_edges:
                        neigh_edges2 |= set(
                            [e2 for e2 in e.neighbor_edges if e2 not in added])
                    to_redraw |= neigh_edges2
                elif o.object_type == 'bond':
                    to_redraw |= set([
                        a for a in o.get_atoms()
                        if a.show and not a in deleted and not a in added
                    ])
                elif o.object_type == 'point':
                    to_redraw.add(o)
                    to_redraw.add(o.parent)

            i += 1

        ## DELETED OBJECTS
        # deleted are known from the top of this def
        for o in deleted:
            if o.object_type not in ('molecule', 'mark') and hasattr(
                    o, 'draw'):
                # no_automatic where possible
                if 'automatic' in inspect.getargspec(o.draw)[0]:
                    o.draw(automatic="none")
                else:
                    o.draw()
            # hacks to ensure complete redraw
            if o.object_type == 'atom':
                to_redraw |= set(
                    [b for b in o.neighbor_edges if b not in deleted])
            elif o.object_type == 'bond':
                to_redraw |= set(
                    [a for a in o.get_atoms() if a.show and not a in deleted])
            elif o.object_type == 'point':
                to_redraw.add(o)
                to_redraw.add(o.parent)

        ## ADDED OBJECTS
        # added are known from the top of this def
        for o in added:
            if o.object_type != 'molecule' and hasattr(o, "delete"):
                o.delete()

        # now redrawing
        # sort the to_redraw
        to_redraw = list(to_redraw)
        to_redraw.sort(key=_redraw_sorting)
        for o in to_redraw:
            if o not in deleted and o.object_type != 'molecule' and hasattr(
                    o, 'redraw'):
                if hasattr(o, "after_undo"):
                    o.after_undo()
                if o.object_type == 'atom':
                    o.redraw(suppress_reposition=1)
                else:
                    o.redraw()

        self.paper.stack = copy.copy(self.stack)
        self.paper.add_bindings()
Exemplo n.º 6
0
  def set_state( self, previous):
    """sets the system to the recorded state (update is done only where necessary,
    not changed values are not touched)."""
    # we need to know about deleted bonds before we try to redraw them (when updating atom)
    deleted = misc.difference( self.objects, previous.objects)
    added = misc.difference( previous.objects, self.objects)
    to_redraw = set()
    ## CHANGED OBJECTS
    i = 0
    for o in self.objects:
      changed = 0
      for a in o.meta__undo_fake:
        # fakes serve only to force redraw in some cases however do not perform any undo
        if self.records[i][a] != getattr( o, a):
          changed = 1
      for a in o.meta__undo_simple:
        if self.records[i][a] != o.__dict__[a]:
          o.__dict__[a] = self.records[i][a]
          if a != 'molecule':  # this jumps a little from the clean, meta-driven design, however saves much time
            changed = 1
      for a in o.meta__undo_copy:
        if self.records[i][a] != o.__dict__[a]:
          o.__dict__[a] = copy.copy( self.records[i][a])
          changed = 1
          # this part is not meta driven, I have to rewrite it one day
          if a == 'bonds':
            o.edges = o.bonds
          elif a == 'atoms':
            o.vertices = o.atoms
          # / end of the shitty patch
      for a in o.meta__undo_properties:
        if hasattr( o, a):
          if self.records[i][a] != getattr( o, a):
            setattr( o, a, self.records[i][a])
            changed = 1

      if changed:
        to_redraw.add( o)
        # some hacks needed to ensure complete redraw
        if o.object_type == 'atom':
          neigh_edges = set( [b for b in o.neighbor_edges if b not in deleted and b not in added])
          to_redraw |= neigh_edges
          # neighboring edges of the atoms edges - needed because of new bond drawing code
          # that takes neighboring edges into account
          neigh_edges2 = set()
          for e in neigh_edges:
            neigh_edges2 |= set([e2 for e2 in e.neighbor_edges if e2 not in added])
          to_redraw |= neigh_edges2
        elif o.object_type == 'bond':
          to_redraw |= set( [a for a in o.get_atoms() if a.show and not a in deleted and not a in added])
        elif o.object_type == 'point':
          to_redraw.add( o)
          to_redraw.add( o.parent)

      i += 1

    ## DELETED OBJECTS
    # deleted are known from the top of this def
    for o in deleted:
      if o.object_type not in ( 'molecule','mark') and hasattr( o, 'draw'):
        # no_automatic where possible
        if 'automatic' in inspect.getargspec( o.draw)[0]:
          o.draw( automatic = "none")
        else:
          o.draw()
      # hacks to ensure complete redraw
      if o.object_type == 'atom':
        to_redraw |= set( [b for b in o.neighbor_edges if b not in deleted])
      elif o.object_type == 'bond':
        to_redraw |= set( [a for a in o.get_atoms() if a.show and not a in deleted])
      elif o.object_type == 'point':
        to_redraw.add( o)
        to_redraw.add( o.parent)

    ## ADDED OBJECTS
    # added are known from the top of this def
    for o in added:
      if o.object_type != 'molecule' and hasattr( o, "delete"):
        o.delete()

    # now redrawing
    # sort the to_redraw
    to_redraw = list( to_redraw)
    to_redraw.sort(key=_redraw_sorting)
    for o in to_redraw:
      if o not in deleted and o.object_type != 'molecule' and hasattr(o,'redraw'):
        if hasattr( o, "after_undo"):
          o.after_undo()
        if o.object_type == 'atom':
          o.redraw( suppress_reposition=1)
        else:
          o.redraw()

    self.paper.stack = copy.copy( self.stack)
    self.paper.add_bindings()
Exemplo n.º 7
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
Exemplo n.º 8
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