コード例 #1
0
    def aromatizeRing(self, ring, center_x, center_y):
        '''
        render a ring that is aromatic and is a regular polygon
        '''
        # first, set all bonds to aromatic
        ringbonds = list(ring.iterateBonds())

        for tkbond in ringbonds:
            bond = self._getBond(tkbond)
            bond.bond_type = 'aromatic'

        # any bond can serve as the anchor for the circle,
        # so we'll just use the last one from the loop
        atom = bond.end_atom

        outer_r, angle = compare_positions(atom.x, atom.y, center_x, center_y)
        # angle is based on raw coordinates - adjust for user-set rotation
        angle += self.options['rotate']

        # outer_r calculated from raw coordinates, must be adjusted
        # for bond scaling that may have taken place
        outer_r *= self.bond_scale

        alpha = ( math.pi / 2 - math.pi / len(ringbonds) )
        inner_r = math.sin(alpha) * outer_r

        arb = AromaticRingBond(self.options, bond, angle, outer_r, inner_r)
        bond.descendants.append(arb)
コード例 #2
0
    def annotateRing(self, ring, is_aromatic):
        '''
        determine center, symmetry and aromatic character of ring
        I wonder if indigo would tell us directly about these ...

        annotate double bonds in rings, or alternatively decorate
        ring with aromatic circle.
        '''
        atoms = set()
        bond_lengths = []
        bonds = []


        for tkbond in ring.iterateBonds():
            bond = self._getBond(tkbond)
            bonds.append(bond)

            atoms.add(self.atoms[bond.start_atom.idx])
            atoms.add(self.atoms[bond.end_atom.idx])
            bond_lengths.append(bond.length)

        if len(bonds) > 8:  # large rings may foul things up, so we skip them.
            return

        bl_max = max(bond_lengths)
        bl_spread = (bl_max - min(bond_lengths)) / bl_max

        # determine ring center
        center_x = sum([atom.x for atom in atoms]) / len(atoms)
        center_y = sum([atom.y for atom in atoms]) / len(atoms)

        # compare distances from center. Also remember atoms and bond
        # angles; if the ring ends up being aromatized, we flag those
        # angles as occupied (by the fancy circle inside the ring).
        atom_angles = []
        center_distances = []

        for atom in atoms:
            length, angle = compare_positions(atom.x, atom.y, center_x, center_y)
            center_distances.append(length)
            atom_angles.append((atom, angle))

        cd_max = max(center_distances)
        cd_spread = (cd_max - min(center_distances)) / cd_max

        tolerance = 0.05
        is_symmetric = (cd_spread <= tolerance and bl_spread <= tolerance)

        if is_aromatic and is_symmetric and self.options['aromatic_circles']:
            # ring meets all requirements to be displayed with circle inside
            self.aromatizeRing(ring, center_x, center_y)
            # flag bond angles as occupied
            for atom, angle in atom_angles:
                atom.bond_angles.append(angle)

        else:   # flag orientation individual bonds - will influence
                # rendering of double bonds
            for bond in bonds:
                bond.is_clockwise(center_x, center_y)