def mark_aromatic_bonds(self): sssr = self.get_smallest_independent_cycles() if len(sssr) > 10: # turn off processing of all cycles - it would be too slow, just use SSSR rings = sssr else: rings = self.get_all_cycles( ) #self.get_smallest_independent_cycles() solved = [1] # we need to repeat it to mark such things as 'badly' drawn naphtalene (no double bond in the centre) while solved: solved = [] for aring in rings: els = [ self._get_atoms_possible_aromatic_electrons(a, aring) for a in aring ] if () in els: continue for comb in common.gen_combinations_of_series(els): if sum(comb) % 4 == 2: bring = self.vertex_subgraph_to_edge_subgraph(aring) for b in bring: b.aromatic = 1 #b.order = 4 solved.append(aring) break for r in solved: rings.remove(r)
def mark_aromatic_bonds( self): sssr = self.get_smallest_independent_cycles() if len( sssr) > 10: # turn off processing of all cycles - it would be too slow, just use SSSR rings = sssr else: rings = self.get_all_cycles() #self.get_smallest_independent_cycles() solved = [1] # we need to repeat it to mark such things as 'badly' drawn naphtalene (no double bond in the centre) while solved: solved = [] for aring in rings: els = [self._get_atoms_possible_aromatic_electrons( a, aring) for a in aring] if () in els: continue for comb in common.gen_combinations_of_series( els): if sum( comb) % 4 == 2: bring = self.vertex_subgraph_to_edge_subgraph( aring) for b in bring: b.aromatic = 1 #b.order = 4 solved.append( aring) break for r in solved: rings.remove( r)
def localize_aromatic_bonds(self): """localizes aromatic bonds (does not relocalize already localized ones), for those that are not aromatic but marked so (it is for instance possible to misuse 'cccc' in smiles to create butadiene) they will be properly localized but marked as non-aromatic""" erings = self.get_smallest_independent_cycles_e() # filter off rings without aromatic bonds erings = filter(lambda x: len([b for b in x if b.aromatic]), erings) rings = map(self.edge_subgraph_to_vertex_subgraph, erings) # sort rings rings.sort( lambda x, y: len(y) % 2 - len(x) % 2) # odd size rings first last_rings = [] while rings: # we have to continue with the neighbor rings of the last_ring (or the rings before) intersection = None if last_rings: aring = None while last_rings: last_ring = last_rings.pop(-1) for ring in rings: intersection = ring & last_ring if intersection: aring = ring last_rings.append(last_ring) break if aring: break if not aring: aring = rings.pop(0) else: rings.remove(aring) else: aring = rings.pop(0) last_rings.append(aring) # convert ring from set to list aring = self.sort_vertices_in_path( aring, start_from=intersection and intersection.pop() or None) # taken from mark_aromatic_bonds els = [ self._get_atoms_possible_aromatic_electrons(a, aring) for a in aring ] if () in els: continue # misuse of aromatic bonds (e.g. by smiles) or e.g. tetrahydronaphtalene for comb in common.gen_combinations_of_series(els): if sum(comb) % 4 == 2: aring.append(aring[0]) comb.append(comb[0]) # at first we process the bonds that are surely single (like C-S-C in thiophene) already_set = None for i in range(len(aring) - 1): if comb[i] + comb[i + 1] != 2: # these bonds must be single b = aring[i].get_edge_leading_to(aring[i + 1]) b.order = 1 already_set = i if already_set != None: # we reorder the comb and aring to start from the already set bonds j = already_set + 1 aring = aring[j:len(aring)] + aring[1:j] aring.insert(0, aring[-1]) comb = comb[j:len(comb)] + comb[1:j] comb.insert(0, comb[-1]) i = 0 while i + 1 < len(aring): if comb[i] + comb[i + 1] == 2: b = aring[i].get_edge_leading_to(aring[i + 1]) assert b != None # should be # to assure alternating bonds bs1 = [ bo for bo in aring[i].get_neighbor_edges() if bo.order == 2 and bo.aromatic and bo != b ] bs2 = [ bo for bo in aring[i + 1].get_neighbor_edges() if bo.order == 2 and bo.aromatic and bo != b ] if len(bs1) == 0 and len(bs2) == 0: b.order = 2 else: b.order = 1 i += 1 break self.localize_fake_aromatic_bonds()
def localize_aromatic_bonds( self): """localizes aromatic bonds (does not relocalize already localized ones), for those that are not aromatic but marked so (it is for instance possible to misuse 'cccc' in smiles to create butadiene) they will be properly localized but marked as non-aromatic""" erings = self.get_smallest_independent_cycles_e() # filter off rings without aromatic bonds erings = filter( lambda x: len( [b for b in x if b.aromatic]), erings) rings = map( self.edge_subgraph_to_vertex_subgraph, erings) # sort rings rings.sort( lambda x,y: len(y)%2 - len(x)%2) # odd size rings first last_rings = [] while rings: # we have to continue with the neighbor rings of the last_ring (or the rings before) intersection = None if last_rings: aring = None while last_rings: last_ring = last_rings.pop( -1) for ring in rings: intersection = ring & last_ring if intersection: aring = ring last_rings.append( last_ring) break if aring: break if not aring: aring = rings.pop(0) else: rings.remove( aring) else: aring = rings.pop(0) last_rings.append( aring) # convert ring from set to list aring = self.sort_vertices_in_path( aring, start_from=intersection and intersection.pop() or None) # taken from mark_aromatic_bonds els = [self._get_atoms_possible_aromatic_electrons( a, aring) for a in aring] if () in els: continue # misuse of aromatic bonds (e.g. by smiles) or e.g. tetrahydronaphtalene for comb in common.gen_combinations_of_series( els): if sum( comb) % 4 == 2: aring.append( aring[0]) comb.append( comb[0]) # at first we process the bonds that are surely single (like C-S-C in thiophene) already_set = None for i in range( len( aring) -1): if comb[i] + comb[i+1] != 2: # these bonds must be single b = aring[i].get_edge_leading_to( aring[i+1]) b.order = 1 already_set = i if already_set != None: # we reorder the comb and aring to start from the already set bonds j = already_set + 1 aring = aring[j:len(aring)] + aring[1:j] aring.insert( 0, aring[-1]) comb = comb[j:len(comb)] + comb[1:j] comb.insert( 0, comb[-1]) i = 0 while i+1 < len( aring): if comb[i] + comb[i+1] == 2: b = aring[i].get_edge_leading_to( aring[i+1]) assert b != None # should be # to assure alternating bonds bs1 = [bo for bo in aring[i].get_neighbor_edges() if bo.order == 2 and bo.aromatic and bo!=b] bs2 = [bo for bo in aring[i+1].get_neighbor_edges() if bo.order == 2 and bo.aromatic and bo!=b] if len( bs1) == 0 and len( bs2) == 0: b.order = 2 else: b.order = 1 i += 1 break self.localize_fake_aromatic_bonds()