Exemplo n.º 1
0
def _moe_ph4_string(pharmacophoric_points: List[PharmacophoricPoint]) -> str:
    """ Returns a string with the necessary info to create a MOE ph4 file.

        Parameters
        ----------
        pharmacophoric_points : List of PharmacophoricPoint
            List with the pharmacophoric points.

        file_name : str
            Name of the file containing the pharmacophore.

        Returns
        ------
        ph4_str : str
            The pharmacophore string.
    """
    oph_to_moe = {
        "aromatic ring": "Aro",
        "hydrophobicity": "Hyd",
        "hb acceptor": "Acc",
        "hb donor": "Don",
        "positive charge": "Cat",
        "negative charge": "Ani",
    }

    now = datetime.datetime.now()
    ph4_str = "#moe:ph4que" + " " + str(now.year) + "." + str(now.month) + "\n"
    ph4_str += "#pharmacophore 5 tag t value *\n"
    ph4_str += "scheme t Unified matchsize i 0 title t s $\n"
    ph4_str += f"#feature {len(pharmacophoric_points)} expr tt color ix x r y r z r r r ebits ix gbits ix\n"

    excluded_spheres = []
    for element in pharmacophoric_points:
        if element.feature_name == "excluded volume":
            excluded_spheres.append(element)
            continue
        feat_name = oph_to_moe[element.feature_name]
        center = puw.get_value(element.center, to_unit="angstroms")
        radius = str(puw.get_value(element.radius, to_unit="angstroms")) + " "
        x = str(center[0]) + " "
        y = str(center[1]) + " "
        z = str(center[2]) + " "
        ph4_str += feat_name + " df2f2 " + x + y + z + radius    
        ph4_str += "0 300 "
    
    if excluded_spheres:
        ph4_str += "\n#volumesphere 90 x r y r z r r r\n"
        for excluded in excluded_spheres:
            center = puw.get_value(excluded.center, to_unit="angstroms")
            radius = str(puw.get_value(excluded.radius, to_unit="angstroms")) + " "
            x = str(center[0]) + " "
            y = str(center[1]) + " "
            z = str(center[2]) + " "
            ph4_str += x + y + z + radius

    ph4_str += "\n#endpharmacophore"

    return ph4_str
Exemplo n.º 2
0
def _pharmer_dict(
        pharmacophoric_points: List[PharmacophoricPoint]) -> Dict[str, Any]:
    """ Returns a Dictionary with the necessary info to construct pharmer pharmacophore. 

        Parameters
        ----------
        pharmacophoric_points : list of openpharmacophore.PharmacophoricPoint
            Pharmacophore points that will be used to construct the dictionary

        Returns
        -------
        pharmacophore_dict : dict
            Dictionary with the necessary info to construct a .json pharmer file. 
    """
    pharmer_element_name = { # dictionary to map openpharmacophore feature names to pharmer feature names
        "aromatic ring": "Aromatic",
        "hydrophobicity": "Hydrophobic",
        "hb acceptor": "HydrogenAcceptor",
        "hb donor": "HydrogenDonor",
        "included volume": "InclusionSphere",
        "excluded volume": "ExclusionSphere",
        "positive charge": "PositiveIon",
        "negative charge": "NegativeIon",
    }
    points = []
    for element in pharmacophoric_points:
        point_dict = {}
        temp_center = puw.get_value(element.center, to_unit='angstroms')
        point_dict["name"] = pharmer_element_name[element.feature_name]
        point_dict["svector"] = {}
        if element.has_direction:
            point_dict["hasvec"] = True
            point_dict["svector"]["x"] = element.direction[0]
            point_dict["svector"]["y"] = element.direction[1]
            point_dict["svector"]["z"] = element.direction[2]
        else:
            point_dict["hasvec"] = False
            point_dict["svector"]["x"] = 1
            point_dict["svector"]["y"] = 0
            point_dict["svector"]["z"] = 0
        point_dict["x"] = temp_center[0]
        point_dict["y"] = temp_center[1]
        point_dict["z"] = temp_center[2]
        point_dict["radius"] = puw.get_value(element.radius,
                                             to_unit='angstroms')
        point_dict["enabled"] = True
        point_dict["vector_on"] = 0
        point_dict["minsize"] = ""
        point_dict["maxsize"] = ""
        point_dict["selected"] = False

        points.append(point_dict)

    pharmacophore_dict = {}
    pharmacophore_dict["points"] = points

    return pharmacophore_dict
Exemplo n.º 3
0
def test_get_unique_pharmacophoric_points(sample_dynamic_pharmacophore):
    dynophore = sample_dynamic_pharmacophore
    dynophore._get_unique_pharmacophoric_points(avg_coordinates=True)

    assert len(dynophore.unique_pharmacophoric_points) == 5

    # Acceptor
    acceptor = dynophore.unique_pharmacophoric_points[0]
    center = puw.get_value(acceptor.center, "angstroms")
    assert acceptor.feature_name == "hb acceptor 1"
    assert acceptor.atom_indices == {10}
    assert acceptor.count == 1
    assert acceptor.frequency == 1 / 10
    assert np.allclose(center, np.array([-0.5, 8.5, 2.4]))

    # Donor 1
    donor_1 = dynophore.unique_pharmacophoric_points[1]
    center = puw.get_value(donor_1.center, "angstroms")
    assert donor_1.feature_name == "hb donor 1"
    assert donor_1.atom_indices == {1}
    assert donor_1.count == 10
    assert donor_1.frequency == 1
    assert len(donor_1.timesteps) == 10
    assert np.allclose(center, np.array([1.45, 0.45, 3.45]))

    # Donor 2
    donor_2 = dynophore.unique_pharmacophoric_points[3]
    center = puw.get_value(donor_2.center, "angstroms")
    assert donor_2.feature_name == "hb donor 2"
    assert donor_2.atom_indices == {8}
    assert donor_2.count == 6
    assert donor_2.frequency == 6 / 10
    assert np.allclose(center, np.array([-4.75, 1.75, -2.15]))

    # Hydrophobic
    hydrophobic = dynophore.unique_pharmacophoric_points[4]
    center = puw.get_value(hydrophobic.center, "angstroms")
    assert hydrophobic.feature_name == "hydrophobicity 1"
    assert hydrophobic.atom_indices == {12}
    assert hydrophobic.count == 1
    assert hydrophobic.frequency == 1 / 10
    assert np.allclose(center, np.array([-0.5, 8.5, 2.4]))

    # Aromatic
    aromatic = dynophore.unique_pharmacophoric_points[2]
    center = puw.get_value(aromatic.center, "angstroms")
    assert aromatic.feature_name == "aromatic ring 1"
    assert aromatic.atom_indices == {2, 3, 4, 5, 6, 7}
    assert aromatic.count == 4
    assert aromatic.frequency == 4 / 10
    assert len(aromatic.timesteps) == 4
    assert np.allclose(center, np.array([-4.85, 1.65, -2.25]))
Exemplo n.º 4
0
def test_from_pharmer():

    points, molecular_system, ligand = from_pharmer(
        "./openpharmacophore/data/pharmacophores/pharmer/1M70.json",
        load_mol_sys=False)
    assert len(points) == 5
    assert molecular_system is None
    assert ligand is None

    assert points[0].feature_name == "hb acceptor"
    assert points[0].has_direction
    assert puw.get_value(points[0].radius, "angstroms") == 0.9999999999999999
    assert np.allclose(puw.get_value(points[0].center, "angstroms"),
                       np.array([21.352, -14.531, 19.625]))
    assert np.allclose(
        points[0].direction,
        np.array(
            [-0.6405836470264256, 0.7029084735090229, -0.3091476492414897]))

    assert points[1].feature_name == "hb acceptor"
    assert points[1].has_direction
    assert puw.get_value(points[1].radius, "angstroms") == 0.9999999999999999
    assert np.allclose(puw.get_value(points[1].center, "angstroms"),
                       np.array([19.355, -18.32, 23.987]))
    assert np.allclose(
        points[1].direction,
        np.array([0.6859059711903811, 0.09092493673854565, 0.721987295292979]))

    assert points[2].feature_name == "hb donor"
    assert points[2].has_direction
    assert puw.get_value(points[2].radius, "angstroms") == 0.9999999999999999
    assert np.allclose(puw.get_value(points[2].center, "angstroms"),
                       np.array([20.977, -16.951, 18.746]))
    assert np.allclose(
        points[2].direction,
        np.array([0.71662539652105, -0.5202950182802607,
                  -0.46447942367105033]))

    assert points[3].feature_name == "negative charge"
    assert not points[3].has_direction
    assert puw.get_value(points[3].radius, "angstroms") == 1.5
    assert np.allclose(puw.get_value(points[3].center, "angstroms"),
                       np.array([21.66899, -15.077667, 20.608334]))

    assert points[4].feature_name == "negative charge"
    assert not points[4].has_direction
    assert puw.get_value(points[4].radius, "angstroms") == 1.9999999999999998
    assert np.allclose(puw.get_value(points[4].center, "angstroms"),
                       np.array([19.985, -19.404402, 22.8422]))
Exemplo n.º 5
0
 def __repr__(self) -> str:
     center = np.around(puw.get_value(self.center, "angstroms"), 2)
     radius = np.around(puw.get_value(self.radius, "angstroms"), 2)
     x, y, z = center[0], center[1], center[2]
     if self.has_direction:
         direction = np.around(self.direction, 4)
         xd, yd, zd = direction[0], direction[1], direction[2]
         return (f"{self.__class__.__name__}("
                 f"feat_type={self.feature_name}; "
                 f"center=({x}, {y}, {z}); radius: {radius}; "
                 f"direction=({xd}, {yd}, {zd}))")
     else:
         return (f"{self.__class__.__name__}("
                 f"feat_type={self.feature_name}; "
                 f"center=({x}, {y}, {z}); radius={radius})")
Exemplo n.º 6
0
    def _plip_hydrophobics(hydrophobics: List[PharmacophoricPoint],
                           radius: float) -> List[PharmacophoricPoint]:
        """ Groups plip hydrophobic points that are to close into a single point.

            Parameters
            ----------
            hydrophobics : list of openpharmacophore.PharmacophoricPoint
                List with the hydrophobic points.

            Returns
            -------
            grouped_points : list of openpharmacophore.PharmacophoricPoint
                List with the grouped points.
        """
        grouped_points = []
        skip = []
        for inx, hyd1 in enumerate(hydrophobics):
            if hyd1 in skip:
                continue
            centroid = hyd1.center
            indices = hyd1.atom_indices
            count = 0
            hyd1_center = puw.get_value(hyd1.center, "angstroms")

            for hyd2 in hydrophobics[inx + 1:]:
                if hyd1 == hyd2:
                    skip.append(hyd2)
                    continue
                hyd2_center = puw.get_value(hyd2.center, "angstroms")
                distance = np.linalg.norm(hyd1_center - hyd2_center)

                if distance <= 2.5:
                    centroid += hyd2.center
                    indices.union(hyd2.atom_indices)
                    count += 1
                    skip.append(hyd2)
            if count > 0:
                centroid /= (count + 1)

            grouped_points.append(
                PharmacophoricPoint(feat_type="hydrophobicity",
                                    center=centroid,
                                    radius=radius,
                                    direction=None,
                                    atom_indices=indices))

        return grouped_points
Exemplo n.º 7
0
def distance_bewteen_pharmacophoric_points(p1: PharmacophoricPoint,
                                           p2: PharmacophoricPoint) -> float:
    """ Compute the distance in angstroms between two pharmacophoric points.
    
        Parameters
        ----------
        p1 : openpharmacophore.pharmacophoric_point
            A pharmacophoric point

        p2 : openpharmacophore.pharmacophoric_point
            A pharmacophoric point
        
        Returns
        -------
        float
            The distance between the pharmacophoric points
    """

    p1_center = puw.get_value(p1.center, "angstroms")
    p2_center = puw.get_value(p2.center, "angstroms")

    return np.linalg.norm(p1_center - p2_center)
Exemplo n.º 8
0
def test_smarts_hydrophobics():

    ligand = Chem.MolFromSmiles(
        "CC1=CC(=CC(=C1OCCCC2=CC(=NO2)C)C)C3=NOC(=N3)C(F)(F)F")
    ligand = generate_conformers(ligand, 1, random_seed=1)
    hydrophobics = SBP()._smarts_hydrophobics(ligand, 1.0)

    assert len(hydrophobics) == 3

    hyd_1 = hydrophobics[0]
    hyd_2 = hydrophobics[2]
    hyd_2_center = puw.get_value(hyd_2.center, "angstroms")
    hyd_2_radius = puw.get_value(hyd_2.radius, "angstroms")
    assert hyd_1 == PharmacophoricPoint(feat_type="hydrophobicity",
                                        center=puw.quantity(
                                            (1.4268, -1.9841, -1.4186),
                                            "angstroms"),
                                        radius=puw.quantity(1.0, "angstroms"))
    assert np.allclose(np.around(hyd_2_center, 3), (-2.130, -0.542, -0.479),
                       rtol=0,
                       atol=1e-04)
    assert np.allclose(hyd_2_radius, hyd_2_radius, rtol=0, atol=1e-03)
Exemplo n.º 9
0
    def to_rdkit(self) -> Tuple[rdkitPharmacophore.Pharmacophore, List[float]]:
        """ Returns an rdkit pharmacophore with the pharmacophoric_points from the original pharmacophore. 
            
            rdkit pharmacophores do not store the pharmacophoric_points radii, so they are returned as well.

            Returns
            -------
            rdkit_pharmacophore : rdkit.Chem.Pharm3D.Pharmacophore
                The rdkit pharmacophore.

            radii : list of float
                List with the radius in angstroms of each pharmacophoric point.
        """
        rdkit_element_name = { # dictionary to map openpharmacophore feature names to rdkit feature names
        "aromatic ring": "Aromatic",
        "hydrophobicity": "Hydrophobe",
        "hb acceptor": "Acceptor",
        "hb donor": "Donor",
        "positive charge": "PosIonizable",
        "negative charge": "NegIonizable",
        }

        points = []
        radii = []

        for element in self._pharmacophoric_points:
            feat_name = rdkit_element_name[element.feature_name]
            center = puw.get_value(element.center, to_unit="angstroms")
            center = Geometry.Point3D(center[0], center[1], center[2])
            points.append(ChemicalFeatures.FreeChemicalFeature(
                feat_name,
                center
            ))
            radius = puw.get_value(element.radius, to_unit="angstroms")
            radii.append(radius)

        rdkit_pharmacophore = rdkitPharmacophore.Pharmacophore(points)
        return rdkit_pharmacophore, radii
Exemplo n.º 10
0
    def add_to_NGLView(self, view: nv.NGLWidget, palette: str = 'openpharmacophore') -> None:
        """Add the pharmacophore representation to a view (NGLWidget) from NGLView.

        Each pharmacophoric element is added to the NGLWidget as a new component.

        Parameters
        ----------
        view : nglview.NGLWidget
            View as NGLView widget where the pharmacophore will be added.

        palette : str or dict
            Color palette name or dictionary. (Default: 'openpharmacophore')

        """
        first_element_index = len(view._ngl_component_ids)
        for ii, element in enumerate(self._pharmacophoric_points):
            # Add Spheres
            center = puw.get_value(element.center, to_unit="angstroms").tolist()
            radius = puw.get_value(element.radius, to_unit="angstroms")
            feature_color = get_color_from_palette_for_feature(element.feature_name, color_palette=palette)
            label = f"{element.feature_name}_{ii}"
            view.shape.add_sphere(center, feature_color, radius, label)

            # Add vectors
            if element.has_direction:
                label = f"{element.feature_name}_vector"
                if element.feature_name == "hb acceptor":
                    end_arrow = puw.get_value(element.center - 2 * radius * puw.quantity(element.direction, "angstroms"), to_unit='angstroms').tolist()
                    view.shape.add_arrow(end_arrow, center, feature_color, 0.2, label)
                else:
                    end_arrow = puw.get_value(element.center + 2 * radius * puw.quantity(element.direction, "angstroms"), to_unit='angstroms').tolist()
                    view.shape.add_arrow(center, end_arrow, feature_color, 0.2, label)
        
        # Add opacity to spheres
        last_element_index = len(view._ngl_component_ids)
        for jj in range(first_element_index, last_element_index):
            view.update_representation(component=jj, opacity=0.8)
Exemplo n.º 11
0
    def __init__(self,
                 feat_type: str,
                 center: Quantity,
                 radius: Quantity,
                 direction: Optional[ArrayLike] = None,
                 atom_indices: Optional[Sequence] = None) -> None:

        # Validate center
        validate_input_quantity(center, {"[L]": 1}, "center", shape=(3, ))
        # Validate radius
        validate_input_quantity(radius, {"[L]": 1}, "radius")
        if puw.get_value(radius, "angstroms") < 0:
            raise NegativeRadiusError("radius must be a positive quantity")
        # Validate direction
        if direction is not None:
            validate_input_array_like(direction, shape=(3, ), name="direction")
        # Validate feat type
        if not isinstance(feat_type, str):
            raise InvalidFeatureType("feat_type must be a string")
        # Validate atom_indices
        if atom_indices is not None:
            if not isinstance(atom_indices, (list, set, tuple)):
                raise OpenPharmacophoreTypeError(
                    "atom_indices must be a list, set or tuple of int")

        if feat_type not in list(feature_to_char.keys()):
            raise InvalidFeatureType(
                f"{feat_type} is not a valid feature type. Valid feature names are {list(feature_to_char.keys())}"
            )

        self.center = puw.standardize(center)
        self.radius = puw.standardize(radius)
        self.feature_name = feat_type
        self.short_name = feature_to_char[feat_type]

        if direction is not None:
            self.direction = direction / np.linalg.norm(direction)
            self.has_direction = True
        else:
            self.direction = None
            self.has_direction = False

        if atom_indices is not None:
            self.atom_indices = set(atom_indices)
        else:
            self.atom_indices = None

        self.pharmacophore_index = 0
        self.count = 1
Exemplo n.º 12
0
def test_from_ligandscout():
    points = from_ligandscout(
        "./openpharmacophore/data/pharmacophores/ligandscout/pharmacophore.pml"
    )
    assert len(points) == 4

    neg_ion = points[2]
    assert neg_ion.feature_name == "negative charge"
    assert np.all(
        np.around(puw.get_value(neg_ion.center, "angstroms"), 1) == np.array(
            [-8.0, 10.0, -9.5]))
    assert puw.get_value(neg_ion.radius, "angstroms") == 1.5

    donor = points[0]
    assert donor.feature_name == "hb donor"
    assert np.all(
        np.around(puw.get_value(donor.center, "angstroms"), 1) == np.array(
            [-8.0, 2.0, -10.0]))
    assert puw.get_value(donor.radius, "angstroms") == 1.5
    dir_expected = np.array(
        [-5.690445899963379, 0.5822541117668152, -10.5515718460083])
    dir_expected /= np.linalg.norm(dir_expected)
    assert np.all(np.around(donor.direction, 2) == np.around(dir_expected, 2))

    ring = points[3]
    assert ring.feature_name == "aromatic ring"
    assert np.all(
        np.around(puw.get_value(ring.center, "angstroms"), 1) == np.array(
            [0.0, 6.5, -3.0]))
    assert puw.get_value(ring.radius, "angstroms") == 1.5
    dir_expected = np.array(
        [-3.8126893043518066, 1.7578959465026855, 0.6093783378601074])
    dir_expected /= np.linalg.norm(dir_expected)
    assert np.all(np.around(ring.direction, 2) == np.around(dir_expected, 2))

    excluded_vol = points[1]
    assert excluded_vol.feature_name == "excluded volume"
    assert np.all(
        np.around(puw.get_value(excluded_vol.center, "angstroms"), 1) ==
        np.array([5.5, 4.5, -2.0]))
    assert round(puw.get_value(excluded_vol.radius, "angstroms"), 1) == 1.0
Exemplo n.º 13
0
def _ligandscout_xml_tree(
        pharmacophoric_points: List[PharmacophoricPoint]) -> ET.ElementTree:
    """ Get an xml element tree necesary to create a ligandscout pharmacophore.

        Parameters
        ----------
        pharmacophoric_points : openpharmacophore.Pharmacophore
            Pharmacophore object that will be saved to a file.

        Returns
        -------
        tree : xml.etree.ElementTree
            The element tree.

    """
    Feature = namedtuple("Feature", ["name", "id"])
    feature_mapper = { # dictionary to map openpharmacophore features to ligandscout
        "aromatic ring": Feature("AR", "ai_"),
        "hydrophobicity": Feature("H", "hi_"),
        "hb acceptor": Feature("HBA", "ha_"),
        "hb donor": Feature("HBD", "hd_"),
        "excluded volume": Feature("exclusion", "ev_"),
        "positive charge": Feature("PI", "pi_"),
        "negative charge": Feature("NI", "ni_"),
    }

    tree = ET.ElementTree("tree")
    document = ET.Element("pharmacophore")
    document.set("name", "pharmacophore.pml")
    document.set("pharmacophoreType", "LIGAND_SCOUT")

    for i, element in enumerate(pharmacophoric_points):
        try:
            feat_name = feature_mapper[element.feature_name].name
        except:  # skip features not supported by ligandscout
            continue
        coords = puw.get_value(element.center, to_unit="angstroms")
        x = str(coords[0])
        y = str(coords[1])
        z = str(coords[2])
        radius = str(puw.get_value(element.radius, to_unit="angstroms"))
        feat_id = feature_mapper[element.feature_name].id + str(i + 1)

        is_point = (feat_name == "PI" or feat_name == "NI" or feat_name == "H"
                    or feat_name == "HBD" or feat_name == "HBA")
        is_vector = element.has_direction and (feat_name == "HBD"
                                               or feat_name == "HBA")

        if is_vector:
            direction = coords - element.direction
            dir_x = str(direction[0])
            dir_y = str(direction[1])
            dir_z = str(direction[2])
            vector = ET.SubElement(document, "vector")
            # Set vector attributes
            vector.set("name", feat_name)
            vector.set("featureId", feat_id)
            vector.set("pointsToLigand", "false")
            vector.set("hasSyntheticProjectedPoint", "false")
            vector.set("optional", "false")
            vector.set("disabled", "false")
            vector.set("weight", "1.0")
            # Add origin tag
            origin = ET.SubElement(vector, "origin")
            origin.set("x3", x)
            origin.set("y3", y)
            origin.set("z3", z)
            origin.set("tolerance", radius)
            # Add target tag
            target = ET.SubElement(vector, "target")
            target.set("x3", dir_x)
            target.set("y3", dir_y)
            target.set("z3", dir_z)
            target.set("tolerance", radius)
        elif is_point:
            point = ET.SubElement(document, "point")
            # Set point attributes
            point.set("name", feat_name)
            point.set("featureId", feat_id)
            point.set("optional", "false")
            point.set("disabled", "false")
            point.set("weight", "1.0")
            # Add position tag
            position = ET.SubElement(point, "position")
            position.set("x3", x)
            position.set("y3", y)
            position.set("z3", z)
            position.set("tolerance", radius)
        elif feat_name == "AR":
            direction = element.direction
            dir_x = str(direction[0])
            dir_y = str(direction[1])
            dir_z = str(direction[2])
            plane = ET.SubElement(document, "plane")
            # Set plane attributes
            plane.set("name", feat_name)
            plane.set("featureId", feat_id)
            plane.set("optional", "false")
            plane.set("disabled", "false")
            plane.set("weight", "1.0")
            # Add position tag
            position = ET.SubElement(plane, "position")
            position.set("x3", x)
            position.set("y3", y)
            position.set("z3", z)
            position.set("tolerance", radius)
            # Add normal tag
            normal = ET.SubElement(plane, "normal")
            normal.set("x3", dir_x)
            normal.set("y3", dir_y)
            normal.set("z3", dir_z)
            normal.set("tolerance", radius)
        elif feat_name == "exclusion":
            volume = ET.SubElement(document, "volume")
            # Set volume attributes
            volume.set("type", "exclusion")
            volume.set("featureId", feat_id)
            volume.set("optional", "false")
            volume.set("disabled", "false")
            volume.set("weight", "1.0")
            # Add position tag
            position = ET.SubElement(volume, "position")
            position.set("x3", x)
            position.set("y3", y)
            position.set("z3", z)
            position.set("tolerance", radius)

    tree._setroot(document)

    return tree, document
Exemplo n.º 14
0
def test_from_moe():
    file_name = "./openpharmacophore/data/pharmacophores/moe/gmp.ph4"
    points = from_moe(file_name)
    assert len(points) == 10

    # HB Acceptor features should be first
    acceptor = points[0]
    assert acceptor.feature_name == "hb acceptor"
    assert np.all(
        np.around(puw.get_value(acceptor.center, "angstroms"), 2) == np.around(
            np.array([0.312, 3.0175, -2.44825]), 2))
    assert np.around(puw.get_value(acceptor.radius, "angstroms"), 2) == 0.57
    acceptor = points[1]
    assert acceptor.feature_name == "hb acceptor"
    assert np.all(
        np.around(puw.get_value(acceptor.center, "angstroms"), 2) == np.around(
            np.array([-1.95875, 2.536, -3.03625]), 2))
    assert np.around(puw.get_value(acceptor.radius, "angstroms"), 2) == 0.62
    acceptor_2 = points[2]
    assert acceptor_2.feature_name == "hb acceptor"
    assert np.all(
        np.around(puw.get_value(acceptor_2.center, "angstroms"), 2)
        == np.around(
            np.array([-0.755095833333333, 6.3286375, -3.96758333333333]), 2))
    assert np.around(puw.get_value(acceptor_2.radius, "angstroms"), 2) == 1.25

    # Donor points
    donor = points[3]
    assert donor.feature_name == "hb donor"
    assert np.all(
        np.around(puw.get_value(donor.center, "angstroms"), 2) == np.around(
            np.array([1.71, 1.43075, -1.4255]), 2))
    assert np.around(puw.get_value(donor.radius, "angstroms"), 2) == 0.51

    # Hydrophobic points
    hyd = points[4]
    assert hyd.feature_name == "hydrophobicity"
    assert np.all(
        np.around(puw.get_value(hyd.center, "angstroms"), 2) == np.around(
            np.array([2.7895, 2.4035, -1.40875]), 2))
    assert np.around(puw.get_value(hyd.radius, "angstroms"), 2) == 0.55
    hyd_2 = points[5]
    assert hyd_2.feature_name == "hydrophobicity"
    assert np.all(
        np.around(puw.get_value(hyd_2.center, "angstroms"), 2) == np.around(
            np.array([-1.54725, -2.979375, -0.961875]), 2))
    assert np.around(puw.get_value(hyd_2.radius, "angstroms"), 2) == 0.74

    # Aromatic Points
    aromatic_1 = points[6]
    assert aromatic_1.feature_name == "aromatic ring"
    assert np.all(
        np.around(puw.get_value(aromatic_1.center, "angstroms"), 2) == np.
        around(np.array([-0.748458333333333, 2.13108333333333, -2.490375]), 2))
    assert np.around(puw.get_value(aromatic_1.radius, "angstroms"), 2) == 0.58
    aromatic_2 = points[7]
    assert aromatic_2.feature_name == "aromatic ring"
    assert np.all(
        np.around(puw.get_value(aromatic_2.center, "angstroms"), 2) ==
        np.around(np.array([-1.719625, -0.0273333333333334, -2.055625]), 2))
    assert np.around(puw.get_value(aromatic_2.radius, "angstroms"), 2) == 0.6
    aromatic_3 = points[8]
    assert aromatic_3.feature_name == "aromatic ring"
    assert np.all(
        np.around(puw.get_value(aromatic_3.center, "angstroms"), 2) ==
        np.around(
            np.array([5.20029166666667, 1.25479166666667, -0.199041666666667]),
            2))
    assert np.around(puw.get_value(aromatic_3.radius, "angstroms"), 2) == 0.61
    aromatic_4 = points[9]
    assert aromatic_4.feature_name == "aromatic ring"
    assert np.all(
        np.around(puw.get_value(aromatic_4.center, "angstroms"), 2)
        == np.around(
            np.array([-0.755095833333333, 6.3286375, -3.96758333333333]), 2))
    assert np.around(puw.get_value(aromatic_4.radius, "angstroms"), 2) == 1.25
Exemplo n.º 15
0
    def add_to_NGLView(self,
                       view,
                       feature_name=None,
                       color_palette='openpharmacophore',
                       color=None,
                       opacity=0.5):
        """ Adding the pharmacophoric point to an NGLview view.

        Parameters
        ----------
        view : NGLView.widget
            NGLview object where the point representations is added.
        color_palette : str or dict, default='openpharmacophore'
            Color palette to show the point representation.
        color : str or list
            Color to show the point representation as HEX or RGB code.
        opacity : float
            The level of opacity. Must be a number between 0 and 1.

        Notes
        -----
        This method does not return a new view but modifies the input object.

        """

        if feature_name is None:
            try:
                feature_name = self.feature_name
            except:
                pass

        if color is None:
            if feature_name is not None:
                color = get_color_from_palette_for_feature(
                    feature_name, color_palette)
            else:
                raise PointWithNoColorError(__documentation_web__)

        color = convert_color_code(color, to_form='rgb')

        radius = puw.get_value(self.radius, to_unit='angstroms')
        center = puw.get_value(self.center, to_unit='angstroms').tolist()

        try:
            n_components = len(view._ngl_component_ids)
        except:
            n_components = 0

        view.shape.add_sphere(center, color, radius, feature_name)
        view.update_representation(component=n_components,
                                   repr_index=0,
                                   opacity=opacity)

        if self.has_direction:
            arrow_radius = 0.2
            end_arrow = puw.get_value(self.center +
                                      self.radius * self.direction,
                                      to_unit='angstroms').tolist()

            view.shape.add_arrow(center, end_arrow, color, arrow_radius)
            view.update_representation(component=n_components + 1,
                                       repr_index=0,
                                       opacity=0.9)
Exemplo n.º 16
0
def _pharmagist_file_info(pharmacophores):
    """ Get necessary info to create a pharmagist mol2 file to store pharmacophores.

        Parameters
        ----------
        pharmacophores : list of openpharmacophore.Pharmacophore or openpharmacophore.Pharmacophore
            Pharmacophore or pharmacophores that will be saved

        Returns
        -------
        doc : list of list
            List where each sublist contains a pharmacophore represented as a mol2 string.
    """
    pharmagist_element_name = { 
        "aromatic ring": "AR ",
        "hydrophobicity": "HYD",
        "hb acceptor": "ACC",
        "hb donor": "DON",
        "positive charge": "CAT",
        "negative charge": "ANI",
        }

    pharmagist_element_specs = { 
            "aromatic ring": "AR ",
            "hydrophobicity": "HYD",
            "hb acceptor": "HB ",
            "hb donor": "HB ",
            "positive charge": "CHG",
            "negative charge": "CHG",
    }

    if not isinstance(pharmacophores, list):
        pharmacophores = [pharmacophores]

    doc = [] # list to store all pharmacophores
    for pharmacophore in pharmacophores:
        lines = ["@<TRIPOS>MOLECULE\n", "@<TRIPOS>ATOM\n"] # list to store all lines for a single pharmacophore
        line = ""
        index = 0
        for element in pharmacophore:
            try:
                feat_name = pharmagist_element_name[element.feature_name]
            except KeyError:
                continue
            element_inx = str(index + 1)
            line += element_inx.rjust(7)
            line += " " + feat_name
            # Get point coordinates
            center = np.around(puw.get_value(element.center, to_unit="angstroms"), 4)
            # Pad coordinates with zeros to the right. Number of zeros depends on sign
            if center[0] < 0:
                x = str(center[0]).ljust(7,"0").rjust(16)
            else:
                x = str(center[0]).ljust(6,"0").rjust(16)
            if center[1] < 0:
                y = str(center[1]).ljust(7,"0").rjust(10)
            else:
                y = str(center[1]).ljust(6,"0").rjust(10)
            if center[2] < 0:
                z = str(center[2]).ljust(7,"0").rjust(10)
            else:
                z = str(center[2]).ljust(6,"0").rjust(10)
            line += x + y + z + " "
            line += pharmagist_element_specs[element.feature_name].rjust(5)
            line += str(index).rjust(5)
            line += pharmagist_element_specs[element.feature_name].rjust(6)
            line += "0.0000\n".rjust(12)
            lines.append(line)
            line = ""
            
            index += 1

        lines.append("@<TRIPOS>BOND\n")
        for l in lines:
            doc.append(l)
        
    return doc
Exemplo n.º 17
0
    def _sb_pharmacophore_points(
            interactions,
            radius: float,
            ligand: Chem.Mol,
            hydrophobics: str = "smarts") -> List[PharmacophoricPoint]:
        """Static method to obtain a list of pharmacophoric points for the protein-ligand complex.

        Parameters
        ----------
        interacions : plip.structure.preparation.PLInteraction
            object containing all interacion data for a single ligand and a protein.
        
        radius : float 
            Radius of the spheres of the pharmacophoric points.

        ligand : rdkit.Chem.Mol
            The ligand in from the protein-ligand complex.
        
        hydrophobics : {"plip", "smarts"}
            Can be "plip" or "smarts". If the former is chosen the hydrophobic points will
            be retrieved from the interactions plip calculates. Else smarts patterns will be used. 

        Returns
        -------
        list of openpharmacophore.pharmacophoric_point.PharmacophoricPoint
            A list of pharmacophoric points.

        """
        radius = puw.quantity(radius, "angstroms")

        # List with all interactions
        interactions = interactions.all_itypes
        # list of pharmacophoric_pharmacophoric_points
        points = []
        # list oh hydrophobic points
        hydrophobic_points = []
        for interaction in interactions:
            interaction_name = type(interaction).__name__

            if interaction_name == "pistack":
                ligand_center = np.array(interaction.ligandring.center)
                protein_center = np.array(interaction.proteinring.center)
                direction = protein_center - ligand_center
                atom_indices = {
                    atom.idx
                    for atom in interaction.ligandring.atoms
                }
                aromatic = PharmacophoricPoint(feat_type="aromatic ring",
                                               center=puw.quantity(
                                                   ligand_center, "angstroms"),
                                               radius=radius,
                                               direction=direction,
                                               atom_indices=atom_indices)
                points.append(aromatic)

            elif interaction_name == "hydroph_interaction":
                if hydrophobics != "plip":
                    continue
                center = puw.quantity(interaction.ligatom.coords, "angstroms")
                atom_inx = {interaction.ligatom.idx}
                hydrophobic = PharmacophoricPoint(feat_type="hydrophobicity",
                                                  center=center,
                                                  radius=radius,
                                                  direction=None,
                                                  atom_indices=atom_inx)
                hydrophobic_points.append(hydrophobic)

            elif interaction_name == "saltbridge":
                if interaction.protispos:
                    # The ligand has a negative charge
                    center = puw.quantity(interaction.negative.center,
                                          "angstroms")
                    atom_indices = {
                        atom.idx
                        for atom in interaction.negative.atoms
                    }
                    charge_sphere = PharmacophoricPoint(
                        feat_type="negative charge",
                        center=center,
                        radius=radius,
                        atom_indices=atom_indices)
                else:
                    # The ligand has a positive charge
                    center = puw.quantity(interaction.positive.center,
                                          "angstroms")
                    atom_indices = {
                        atom.idx
                        for atom in interaction.positive.atoms
                    }
                    charge_sphere = PharmacophoricPoint(
                        feat_type="positive charge",
                        center=center,
                        radius=radius,
                        atom_indices=atom_indices)
                points.append(charge_sphere)

            elif interaction_name == "hbond":
                if interaction.protisdon:
                    # The ligand has an acceptor atom
                    ligand_acceptor_center = np.array(interaction.a.coords)
                    ligand_acceptor_inx = {interaction.a.idx}
                    protein_donor_center = np.array(interaction.d.coords)
                    direction = ligand_acceptor_center - protein_donor_center
                    acceptor = PharmacophoricPoint(
                        feat_type="hb acceptor",
                        center=puw.quantity(ligand_acceptor_center,
                                            "angstroms"),
                        radius=radius,
                        direction=direction,
                        atom_indices=ligand_acceptor_inx)
                    points.append(acceptor)
                else:
                    # The ligand has a donor atom
                    ligand_donor_center = np.array(interaction.d.coords)
                    ligand_donor_inx = {interaction.d.idx}
                    protein_acceptor_center = np.array(interaction.a.coords)
                    direction = protein_acceptor_center - ligand_donor_center
                    donor = PharmacophoricPoint(feat_type="hb donor",
                                                center=puw.quantity(
                                                    ligand_donor_center,
                                                    "angstroms"),
                                                radius=radius,
                                                direction=direction,
                                                atom_indices=ligand_donor_inx)
                    points.append(donor)
            else:
                # TODO: Incorporate other features such as halogenbonds, waterbridges and metal complexes
                continue

        # Remove duplicate points
        points_filtered = []
        for p in points:
            if p not in points_filtered:
                points_filtered.append(p)

        # Group hydrophobic interactions within a distance of 2.5 angstroms
        if len(hydrophobic_points) > 1:
            hydrophobic_points = StructuredBasedPharmacophore._plip_hydrophobics(
                hydrophobic_points, radius)

        if hydrophobics == "smarts":
            radius = puw.get_value(radius, "angstroms")
            hydrophobic_points = StructuredBasedPharmacophore._smarts_hydrophobics(
                ligand, radius)

        return points_filtered + hydrophobic_points
Exemplo n.º 18
0
def test_PharmacophoricPoint():

    # First we test that it raises the correct exceptions when the input arguments
    # are not valid

    radius = puw.quantity(1.0, "angstroms")
    center = puw.quantity([1.0, 1.0, 1.0], "angstroms")

    # Test that center is validated correctly
    with pytest.raises(exc.IsNotQuantityError,
                       match="center is not a quantity"):
        PharmacophoricPoint(feat_type="hb donor",
                            center=[1, 2, 3],
                            radius=radius)
    with pytest.raises(exc.WrongDimensionalityError,
                       match="center has dimensionality"):
        PharmacophoricPoint(feat_type="hb donor",
                            center=puw.quantity([1.0, 1.0, 1.0], "seconds"),
                            radius=radius)
    with pytest.raises(exc.BadShapeError, match="center has shape"):
        PharmacophoricPoint(feat_type="hb donor",
                            center=puw.quantity([1.0, 1.0], "angstroms"),
                            radius=radius)
    # Test for radius
    with pytest.raises(exc.IsNotQuantityError,
                       match="radius is not a quantity"):
        PharmacophoricPoint(feat_type="hb donor", center=center, radius=1.0)
    with pytest.raises(exc.NegativeRadiusError,
                       match="radius must be a positive"):
        PharmacophoricPoint(feat_type="hb donor",
                            center=center,
                            radius=puw.quantity(-1.0, "angstroms"))
    with pytest.raises(exc.WrongDimensionalityError,
                       match="radius has dimensionality"):
        PharmacophoricPoint(feat_type="hb donor",
                            center=center,
                            radius=puw.quantity(1.0, "seconds"))
    # Test feature type
    with pytest.raises(exc.InvalidFeatureType,
                       match="is not a valid feature type"):
        PharmacophoricPoint(feat_type="rubber duck",
                            center=center,
                            radius=radius)
    with pytest.raises(exc.OpenPharmacophoreTypeError,
                       match="atom_indices must be"):
        PharmacophoricPoint(feat_type="hb donor",
                            center=center,
                            radius=radius,
                            atom_indices=1)

    feat_name = "hb donor"
    atom_inxs = (3, 4, 5, 6)

    donor_1 = PharmacophoricPoint(feat_name, center, radius, None, atom_inxs)
    donor_2 = PharmacophoricPoint(feat_name,
                                  center,
                                  radius,
                                  direction=np.array([1.0, 1.0, 1.0]),
                                  atom_indices=atom_inxs)

    assert donor_1.has_direction == False
    assert np.allclose(puw.get_value(donor_1.center, "angstroms"),
                       np.array([1.0, 1.0, 1.0]))
    assert np.allclose(puw.get_value(donor_1.radius, "angstroms"), 1.0)
    assert atom_inxs == (3, 4, 5, 6)

    feat_name = "aromatic ring"
    center = puw.quantity([1.5, -2.0, 3.2], "angstroms")
    radius = puw.quantity(1.5, "angstroms")
    direction = np.array([1.0, 1.0, 1.0])
    atom_inxs = None

    ring = PharmacophoricPoint(feat_name, center, radius, direction, atom_inxs)
    assert ring.has_direction == True
    assert ring.atom_indices is None
    assert np.allclose(puw.get_value(ring.center, "angstroms"),
                       np.array([1.5, -2.0, 3.2]))
    assert np.allclose(puw.get_value(ring.radius, "angstroms"), 1.5)
    assert np.allclose(
        ring.direction,
        np.array([[1.0, 1.0, 1.0]]) /
        np.linalg.norm(np.array([1.0, 1.0, 1.0])))

    assert donor_1 != ring
    assert donor_2 != donor_1
Exemplo n.º 19
0
def validate_input_quantity(quantity,
                            dimensionality,
                            name,
                            dtype=(float, int, np.int64, np.float32),
                            shape=None):
    """ Check whether a quantity is of the correct dimenstionality, shape and data type

        Parameters
        ----------
        quantity : pyunitwizard.Quantity
            The quantity object that will be validated.
        
        dimensionality : dict
            A dictionary with the expected dimensionality of the quantity.
        
        name : str
            The name or label of the quantity that is being validated.
            
        dtype : tuple, default=(float, int, np.int64, np.float32)
            The type or types that the quantity is expected to have
        
        shape :  tuple, optional
            The shape that the quantity is expected to have. If the quantity is a scalar
            this argument shouldn't be passed.
            
        Raises
        -------
        IsNotQuantityError
            If it is not a pyunitwizar quantity.
        
        WrongDimensionalityError
            If the dimensionality doesn't match with the required one.
        
        QuantityDataTypeError
            If the datatype is not of the expected types.
        
        BadShapeError
            If a non scalar quantity has an incorrect shape.
        
    """
    if not isinstance(quantity, pint.Quantity):
        raise IsNotQuantityError(f"{name} is not a quantity")

    quantity_dim = {
        dim: val
        for dim, val in puw.get_dimensionality(quantity).items() if val != 0
    }

    if quantity_dim != dimensionality:
        raise WrongDimensionalityError(
            f"{name} has dimensionality {quantity_dim}. Expected {dimensionality}."
        )

    quantity_val = puw.get_value(quantity)
    if isinstance(quantity_val, np.ndarray):
        quantity_val = quantity_val[0]
    if not isinstance(quantity_val, dtype):
        raise QuantityDataTypeError(
            f"{name} has data type {type(quantity_val)}. Expected {dtype}.")

    if shape and isinstance(puw.get_value(quantity), np.ndarray):
        quantity_shape = puw.get_value(quantity).shape
        if quantity_shape != shape:
            raise BadShapeError(
                f"{name} has shape {quantity_shape}. Expected Shape {shape}")