Esempio n. 1
0
    def _build_atoms(self):
        """It builds the atoms of the molecule."""

        from peleffy.utils import Logger
        logger = Logger()

        coords = RDKitToolkitWrapper().get_coordinates(self.molecule)

        for index, (atom_name, atom_type, sigma, epsilon, charge,
                    SGB_radius, vdW_radius, gamma, alpha) \
                in enumerate(self.parameters.atom_iterator):
            atom = Atom(index=index,
                        PDB_name=atom_name,
                        OPLS_type=atom_type,
                        x=coords[index][0],
                        y=coords[index][1],
                        z=coords[index][2],
                        sigma=sigma,
                        epsilon=epsilon,
                        charge=charge,
                        born_radius=SGB_radius,
                        SASA_radius=vdW_radius,
                        nonpolar_gamma=gamma,
                        nonpolar_alpha=alpha)
            self.add_atom(atom)

        for atom in self.atoms:
            if atom.index in self.molecule.graph.core_nodes:
                atom.set_as_core()
            else:
                atom.set_as_branch()

        # Start from an atom from the core
        absolute_parent = None
        for atom in self.atoms:
            if atom.core:
                absolute_parent = atom.index
                break
        else:
            logger.error('Error: no core atom found in molecule ' +
                         '{}'.format(self.molecule.name))

        # Get parent indexes from the molecular graph
        parent_idxs = self.molecule.graph.get_parents(absolute_parent)

        # Assert parent_idxs has right length
        if len(parent_idxs) != len(self.atoms):
            logger.error('Error: no core atom found in molecule ' +
                         '{}'.format(self.molecule.name))

        for atom in self.atoms:
            parent_idx = parent_idxs[atom.index]
            if parent_idx is not None:
                atom.set_parent(self.atoms[parent_idx])
Esempio n. 2
0
    def get_parents(self, parent):
        """
        It sets the parent of each atom according to the molecular graph.

        Parameters
        ----------
        parent : int
            The index of the node to use as the absolute parent

        Returns
        -------
        parents : dict[int, int]
            A dictionary containing the index of the parent of each
            atom according to the molecular graph, keyed by the index
            of each child
        """
        def recursive_child_visitor(parent, parents, already_visited=set()):
            """
            A recursive function that hierarchically visits all the childs of
            each atom.

            Parameters
            ----------
            parent : int
                The index of the atom whose childs will be visited
            parents : dict[int, int]
                A dictionary containing the index of the parent of each
                atom according to the molecular graph, keyed by the index
            visited_neighbors : set[int]
                The updated set that contains the indexes of the atoms
                that have already been visited

            Returns
            -------
            parents : dict[int, int]
                A dictionary containing the index of the parent of each
                atom according to the molecular graph, keyed by the index
                of each child
            visited_neighbors : set[int]
                The updated set that contains the indexes of the atoms
                that have already been visited
            """
            if parent in already_visited:
                return already_visited

            already_visited.add(parent)

            childs = self.neighbors(parent)

            for child in childs:
                if child in already_visited:
                    continue
                parents[child] = parent
                parents, already_visited = recursive_child_visitor(
                    child, parents, already_visited)

            return parents, already_visited

        # Initialize the parents dictionary
        parents = {parent: None}

        parents, already_visited = recursive_child_visitor(parent, parents)

        # Assert absolut parent is the only with a None parent value
        if parents[parent] is not None or \
                sum([int(parents[i] is not None) for i in self.nodes]) \
                != len(self.nodes) - 1:

            from peleffy.utils import Logger
            logger = Logger()
            logger.error('Error: found descendant without parent')

        return parents
Esempio n. 3
0
    def _read_and_fix_pdb(self, path):
        """
        It reads the input PDB file returns the corresponding PDB block.
        It also applies some modifications, in case it requires some
        fixing prior running the parser.

        Parameters
        ----------
        path : str
            The path to a PDB with the molecule structure

        Returns
        -------
        pdb_block : str
            The corresponding PDB block, with applied fixes if required
        """
        log = Logger()

        # Skip PDB fixing if it has been deactivated
        if not self.fix_pdb:
            with open(path) as pdb_file:
                pdb_block = pdb_file.read()

            return pdb_block

        # Fix PDB
        missing_element = False
        any_fail = False
        pdb_block = ''
        with open(path) as pdb_file:
            for line in pdb_file:
                if line.startswith('ATOM') or line.startswith('HETATM'):
                    if len(line) < 78 or line[76:78] == '  ':
                        missing_element = True
                        atom_name = line[12:16]
                        # Try to infer element from atom name
                        inferred_element = ''.join([
                            c for c in atom_name
                            if not c.isdigit() and c != ' '
                        ])

                        # Format properly the element identifier
                        if len(inferred_element) == 1:
                            inferred_element = inferred_element.upper()
                        elif len(inferred_element) == 2:
                            inferred_element = inferred_element[0].upper() + \
                                inferred_element[1].lower()
                        else:
                            # We were expecting an element identifier of 1 or 2 chars
                            any_fail = True
                            break

                        # Remove line breaks, if any
                        line = line.strip()

                        # Fill a short line with white spaces
                        while (len(line) < 79):
                            line += ' '

                        # Add element to line (right-justified)
                        line = line[:76] + '{:>2s}'.format(inferred_element) \
                            + line[79:] + '\n'

                pdb_block += line

        if missing_element:
            log.warning("Warning: input PDB has no information about atom " +
                        "elements and they were inferred from atom names. " +
                        "Please, verify that the resulting elements are " +
                        "correct")

        if any_fail:
            log.error("Error: PDB could not be fixed")
            with open(path) as pdb_file:
                pdb_block = pdb_file.read()

        return pdb_block