Exemple #1
0
    def compute_salt_bridges(self):

        salts = []
        [
            self.reps.remove(index)
            for index, rep in reversed(list(enumerate(self.reps.replist)))
        ]

        metr = MetricDistance('sidechain and acidic and element O',
                              'sidechain and basic and element N',
                              metric="contacts",
                              threshold=3.2,
                              pbc=False)
        try:
            data = metr.project(self)
            mapping = metr.getMapping(self)

            if len(np.shape(data)) > 1:
                data = data[0].copy()  # handling NMR structures

            self.reps.add(sel='protein', style='NewCartoon', color=8)

            if mapping[data].atomIndexes.values.any():
                for salt in mapping[data].atomIndexes.values:
                    resid1 = self.get(
                        "resid", sel=f"same residue as index {salt[0]}")[0]
                    chain1 = self.get(
                        "chain", sel=f"same residue as index {salt[0]}")[0]
                    resid2 = self.get(
                        "resid", sel=f"same residue as index {salt[1]}")[0]
                    chain2 = self.get(
                        "chain", sel=f"same residue as index {salt[1]}")[0]

                    if [resid1, resid2] not in salts:
                        salts.append({
                            "residues": [int(resid1), int(resid2)],
                            "chain": [chain1, chain2]
                        })
                        self.reps.add(f"protein and resid {resid1}",
                                      style="Licorice",
                                      color="1")
                        self.reps.add(f"protein and resid {resid2}",
                                      style="Licorice",
                                      color="0")
        except:
            logger.error("Molecule has no basic or acidic residues")
            raise

        graph = make_graph_salts(salts)
        comp, _ = label_components(graph)
        if comp.a.size != 0:
            salts = add_networks_salts(graph, comp)
        else:
            logger.warning('No salt bridges present in the structure')
        return salts
Exemple #2
0
    def plot_curves(self, query: str):
        """ Plots the distance between the alpha carbons in the structure for the fragment region along with the number of backbone clashes of the resulting chimera for each position

        :param dst: np.ndarray: an array containign the distance for each fragment position
        :param bbContacts1: an array containing the number of bb contacts for each fragment position for the resulting chimera of combination query-subject
        :param bbContacts2: an array containing the number of bb contacts for each fragment position for the resulting chimera of combination subject - query
        
        :return: a matplotlib.pyplot figure.
        """
        if self.chim_positions is None:
            logger.error("You need to build the chimeras before plotting. Call build_chimeras()")
            return

        dst = self.global_dst[0]

        residues = self.qPDB.get("resid", sel="index %s" % ' '.join(map(str, self.global_qpairs[0])))

        resids = {}
        distances = {}

        for key, value in self.chim_positions.items():
            if value:
                resids[key] = self.qPDB.get("resid", sel="index %s" % ' '.join(map(str, value)))
            else:
                resids[key] = np.zeros(0)
        for key, value in resids.items():
            if value.any():
                indices = [index for index, resi in enumerate(residues) if resi in value]
                distances[key] = [distance for index, distance in enumerate(dst) if index in indices]
            else:
                distances[key] = []

        color = [('#FCB711', "X"), ('#CC004C', "x"), ('gray', 'o'), ('gray', "o"), ('black', ".")]
        colors = dict(zip(resids.keys(), color))

        fig, ax = plt.subplots(figsize=(12, 9))
        ax.plot(residues, dst, '-', color='black', label='distance q-s')
        ax.set_xlabel(f"Residue in the fragment relative to domain {query}", fontsize=24)
        ax.set_ylabel(r'Distance ($\AA$)', fontsize=24)
        i = 0
        for key, value in sorted(resids.items()):
            if value.any():
                i += 1
                ax.plot(value, distances[key], colors[key][1], markersize=18, color=colors[key][0], label=key)

        ax.tick_params(labelsize=20)
        ax.tick_params(labelsize=20)
        ax.legend(loc=9, bbox_to_anchor=(0.5, 1.35), fontsize=18)
        plt.show()
Exemple #3
0
def get_tmalign_output(mobile: str, target: str,
                       matrix_filename: str) -> np.ndarray:
    """Reads the output matrix of TM align

    :param mobile: path to the query pdb file
    :param target: path to the subject pdb file
    """
    try:
        subprocess.check_output(
            [TM_BIN, mobile, target, '-m', matrix_filename, '-o', "TM.sup"])
    except Exception as e:
        logger.error(f"TMalign cannot align the molecules. Error follows {e}")
    matrot = [[None] * 4] * 3
    with open(matrix_filename, "r") as inputfile:
        for i, line in enumerate(inputfile.readlines()[2:5]):
            matrot[i] = [float(n) for n in line.strip().split()[1:]]

    # os.remove(matrix_filename)
    return np.array(matrot)
Exemple #4
0
    def get_alignment(self, query: str, no: str) -> HHpredHitAlignment:
        """ Obtain the HHS alignment 'no' for query 'query'.
        Only the alignment from the fragment region is retrieved.
        This implies that when the fragment is not located in the
        N-terminus hit.q_start and the position in the output won't
        be the same. For example, if q_start = 20, that aminoacid is
        in position 0 in aln.query.

        :param query: str. Domain query
        :param no: int. Specifies the position in the file (alignment with subject)

        :return: HHpredHitAlignment. Alignment between query and subject for the fragment region.
        """

        hhF = get_FUZZLE_hhs(query)
        try:
            hh = HHOutputParser().parse_file(hhF)
            pair = hh[int(no) - 1]
            aln = pair.alignment
            return aln
        except Exception as e:
            logger.error(f"Parsing of {hhF} failed. Error follows: {e}")
Exemple #5
0
    def compute_salt_bridges(self):

        salts = []
        [
            self.reps.remove(index)
            for index, rep in reversed(list(enumerate(self.reps.replist)))
        ]
        metr = MetricDistance('sidechain and acidic and element O',
                              'sidechain and basic and element N',
                              metric="contacts",
                              threshold=3.2,
                              pbc=False)
        try:
            data = metr.project(self)
        except:
            logger.error("Molecule has no basic or acidic residues")
            raise
        if len(np.shape(data)) > 1:
            data = data[0].copy()  # handling NMR structures
        mapping = metr.getMapping(self)
        self.reps.add(sel='protein', style='NewCartoon', color=8)
        if mapping[data].atomIndexes.values.any():
            for bond in mapping[data].atomIndexes.values:
                resid1 = self.get("resid",
                                  sel=f"same residue as index {bond[0]}")[0]
                resid2 = self.get("resid",
                                  sel=f"same residue as index {bond[1]}")[0]
                if [resid1, resid2] not in salts:
                    salts.append([resid1, resid2])
                self.reps.add(f"protein and resid {resid1}",
                              style="Licorice",
                              color="1")
                self.reps.add(f"protein and resid {resid2}",
                              style="Licorice",
                              color="0")
        else:
            logger.warning("No salt bridges found in this protein")

        return salts
Exemple #6
0
    def build_chimeras(self, partial_alignment: bool = False, cutoff_distance: float = 1) -> Dict[str, Chimera]:
        """ Build all possible chimeras between the two proteins that fulfill
        these two criteria:
        1) That the distance between the fusion points is below the cutoff distance
        2) That the resulting chimera does not present any backbone clashes

        :return: A dictionary with all the possible chimeras
        """
        if self.dst is None:
            logger.error("You need to align the structures before building the chimeras")

        chimeras = {}
        outcomes = ['Query N-terminal', 'Subject N-terminal', 'Not enough mutations Query N-terminal',
                    'Not enough mutations Subject N-terminal', 'Backbone clash']
        self.chim_positions = dict(zip(outcomes, [[] for i in range(len(outcomes))]))

        q_indices = self.qPDB.get("index", sel="protein and name CA")
        qstart = min(q_indices)
        qend = max(q_indices)

        s_indices = self.sPDB.get("index", sel="protein and name CA")
        sstart = min(s_indices)
        send = max(s_indices)

        if partial_alignment is False:
            qpairs = self.global_qpairs
            spairs = self.global_spairs
            dst = self.global_dst
        else:
            qpairs = self.qpairs
            spairs = self.spairs
            dst = self.dst

        # Get the positions in the fragment closer than the cutoff
        for aln_index, chunk in enumerate(dst):
            if aln_index not in self.saPDB:
                logger.error(f"Alignment {aln_index+1} was not produced. Skipping to next alignment.")
                continue
            fusion_points = [index for index, distance in enumerate(chunk) if distance < cutoff_distance]
            # Build query-subject chimera
            for index in fusion_points:
                qMOL = self.qaPDB[0].copy()
                sMOL = self.saPDB[aln_index].copy()
                xo_query = qpairs[aln_index][index]
                xo_subject = spairs[aln_index][index]
                xo_index = [index for index, number in enumerate(self.global_qpairs[0]) if number == xo_query][0]
                residues = self.qPDB.get("resid", sel="index %s" % ' '.join(map(str, self.global_qpairs[0])))
                xo_resid = residues[xo_index]
                try:
                    xo_query_1 = qpairs[aln_index][index + 1]
                    xo_subject_1 = spairs[aln_index][index + 1]
                except:
                    # Position corresponds to C-terminus limit of the fragment
                    xo_query_1 = [i + 1 for i, qindex in enumerate(q_indices) if qindex == xo_query][0]
                    xo_subject_1 = [i + 1 for i, sindex in enumerate(s_indices) if sindex == xo_subject][0]

                # Combination query-subject
                try:
                    chimera1, xo = self._construct_chimera(qMOL, sMOL, qstart, xo_query,
                                                           xo_subject_1, send, 0)

                    self.chim_positions['Query N-terminal'].append(xo_query)
                    chimeras[f"comb1_{xo_resid}"] = chimera1
                    chimeras[f"comb1_{xo_resid}"].add_crossover(xo)
                except NotDiverseChimeraError:
                    self.chim_positions['Not enough mutations Query N-terminal'].append(xo_query)
                except BackboneClashError:
                    self.chim_positions['Backbone clash'].append(xo_query)

                # Combination subject-query
                try:
                    chimera2, xo = self._construct_chimera(qMOL, sMOL, xo_query_1, qend,
                                                           sstart, xo_subject, 1)

                    self.chim_positions['Subject N-terminal'].append(xo_query)
                    chimeras[f"comb2_{xo_resid}"] = chimera2
                    chimeras[f"comb2_{xo_resid}"].add_crossover(xo)
                except NotDiverseChimeraError:
                    self.chim_positions['Not enough mutations Subject N-terminal'].append(xo_query)
                except BackboneClashError:
                    self.chim_positions['Backbone clash'].append(xo_query)

        if not chimeras:
            logger.warning("No combination of query and subject produced a chimera that matched the criteria")

        return chimeras