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.")
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.")
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]
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]
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()
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()
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
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