Skip to content

Commit

Permalink
Implementation of Interaction Occurence Percentage in LigNetwork (#234)
Browse files Browse the repository at this point in the history
* Update network.py

Addition of Occurence Percentage

* Update CHANGELOG.md

added change

* chore: expose interaction data as both label and hover title

* chore: fix ruff

---------

Co-authored-by: Cédric Bouysset <[email protected]>
  • Loading branch information
talagayev and cbouy authored Dec 18, 2024
1 parent 9ab0e5c commit f1fcb31
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 19 deletions.
11 changes: 8 additions & 3 deletions .github/workflows/formatting_linting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,17 @@ jobs:
uses: actions/checkout@v4

- name: Code formatting
uses: chartboost/ruff-action@v1
uses: astral-sh/ruff-action@v2
with:
args: "check --preview"
args: "format --diff"

- name: Notebook formatting
uses: psf/black@stable
with:
src: "docs/notebooks/"
jupyter: true
jupyter: true

- name: Code linting
uses: astral-sh/ruff-action@v2
with:
args: "check --preview --diff"
9 changes: 6 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- `VdWContact` now accepts a `preset` parameter to easily use different van der Waals radii values:
one of `mdanalysis` (default), `rdkit`, or `csd`.
- `LigNetwork` now optionally displays the percentage of interaction occurence when
`show_interaction_data` is enabled. The type of data shown on both the label and
hover title can be modified.
- `VdWContact` now accepts a `preset` parameter to easily use different van der Waals
radii values: one of `mdanalysis` (default), `rdkit`, or `csd`.
- `IFP.interactions()` iterator that yields all interaction data for a given frame in
a single flat structure. This makes iterating over the `fp.ifp` results a bit
easier / less nested.
Expand Down Expand Up @@ -323,4 +326,4 @@ tests.

## [0.2.1] - 2019-10-02

Base version for this changelog
Base version for this changelog
18 changes: 16 additions & 2 deletions prolif/fingerprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ def run(

converter_kwargs = converter_kwargs or ({}, {})
if n_jobs is None:
n_jobs = int(os.environ.get("PROLIF_N_JOBS", 0)) or None
n_jobs = int(os.environ.get("PROLIF_N_JOBS", "0")) or None
if residues == "all":
residues = list(Molecule.from_mda(prot, **converter_kwargs[1]).residues)
if n_jobs != 1:
Expand Down Expand Up @@ -869,6 +869,8 @@ def plot_lignetwork(
carbon: float = 0.16,
width: str = "100%",
height: str = "500px",
fontsize: int = 20,
show_interaction_data: bool = False,
):
"""Generate and display a :class:`~prolif.plotting.network.LigNetwork` plot from
a fingerprint object that has been used to run an analysis.
Expand Down Expand Up @@ -910,6 +912,10 @@ def plot_lignetwork(
Width of the IFrame window.
height : str
Height of the IFrame window.
fontsize: int
Font size used for the atoms, residues, and edge labels.
show_interaction_data: bool
Show the occurence of each interaction on the corresponding edge.
Notes
-----
Expand All @@ -924,6 +930,9 @@ def plot_lignetwork(
:class:`prolif.plotting.network.LigNetwork`
.. versionadded:: 2.0.0
.. versionchanged:: 2.1.0
Added the ``show_interaction_data`` argument and exposed the ``fontsize``.
"""
from prolif.plotting.network import LigNetwork

Expand All @@ -941,7 +950,12 @@ def plot_lignetwork(
rotation=rotation,
carbon=carbon,
)
return ligplot.display(width=width, height=height)
return ligplot.display(
width=width,
height=height,
fontsize=fontsize,
show_interaction_data=show_interaction_data,
)

def plot_barcode(
self,
Expand Down
4 changes: 2 additions & 2 deletions prolif/parallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class TrajectoryPool:
"""

def __init__(
self, n_processes, fingerprint, residues, tqdm_kwargs, rdkitconverter_kwargs,
self, n_processes, fingerprint, residues, tqdm_kwargs, rdkitconverter_kwargs
):
self.tqdm_kwargs = tqdm_kwargs
self.tracker = Value(c_uint32, lock=True)
Expand Down Expand Up @@ -142,7 +142,7 @@ def executor(cls, args):
lig_mol = Molecule.from_mda(lig, **cls.converter_kwargs[0])
prot_mol = Molecule.from_mda(prot, **cls.converter_kwargs[1])
data = cls.fp.generate(
lig_mol, prot_mol, residues=cls.residues, metadata=True,
lig_mol, prot_mol, residues=cls.residues, metadata=True
)
ifp[int(ts.frame)] = data
with cls.tracker.get_lock():
Expand Down
46 changes: 39 additions & 7 deletions prolif/plotting/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ class LigNetwork:
more control and allow them to provide their own 2D coordinates. Added support
for displaying peptides as the "ligand". Changed the default color for
VanDerWaals.
.. versionchanged:: 2.1.0
Added the ``show_interaction_data`` argument and exposed the ``fontsize`` in
``display``.
"""

COLORS: ClassVar = {
Expand Down Expand Up @@ -265,6 +269,8 @@ def __init__(
self._default_interaction_color = "#dbdbdb"
self._non_single_bond_spacing = 0.06
self._dash = [10]
self._edge_title_formatter = "{interaction}: {distance:.2f}Å"
self._edge_label_formatter = "{weight_pct:.0f}%"
# regroup interactions of the same color
temp = defaultdict(list)
interactions = set(df.index.get_level_values("interaction").unique())
Expand Down Expand Up @@ -491,10 +497,10 @@ def _make_non_single_bond(self, ids, btype):
for perp in (p, -p):
for point in xyz:
xy = point[:2] + perp * dist
_id = hash(xy.tobytes())
nodes.append(_id)
self.nodes[_id] = {
"id": _id,
id_ = hash(xy.tobytes())
nodes.append(id_)
self.nodes[id_] = {
"id": id_,
"x": xy[0],
"y": xy[1],
"shape": "text",
Expand Down Expand Up @@ -577,10 +583,16 @@ def _make_interactions(self, mass=2):
else:
i = self._DISPLAYED_ATOM.get(interaction, 0)
origin = lig_indices[i]
int_data = {
"interaction": interaction,
"distance": distance,
"weight": weight,
"weight_pct": weight * 100,
}
edge = {
"from": origin,
"to": prot_res,
"title": f"{interaction}: {distance:.2f}Å",
"title": self._edge_title_formatter.format_map(int_data),
"interaction_type": self._interaction_types.get(
interaction,
interaction,
Expand All @@ -594,6 +606,9 @@ def _make_interactions(self, mass=2):
"width": weight * self._max_interaction_width,
"group": "interaction",
}
if self.show_interaction_data:
edge["label"] = self._edge_label_formatter.format_map(int_data)
edge["font"] = self._edge_label_font
self.edges.append(edge)

def _get_ring_centroid(self, indices):
Expand Down Expand Up @@ -635,10 +650,19 @@ def _make_graph_data(self):
self._patch_hydrogens()
self.nodes = list(self.nodes.values())

def _get_js(self, width="100%", height="500px", div_id="mynetwork", fontsize=20):
def _get_js(
self,
width="100%",
height="500px",
div_id="mynetwork",
fontsize=20,
show_interaction_data=False,
):
"""Returns the JavaScript code to draw the network"""
self.width = width
self.height = height
self.show_interaction_data = show_interaction_data
self._edge_label_font = {"size": fontsize}
self._make_graph_data()
options = {
"width": width,
Expand Down Expand Up @@ -816,7 +840,15 @@ def _get_legend(self, height="90px"):

@requires("IPython.display")
def display(self, **kwargs):
"""Prepare and display the network"""
"""Prepare and display the network.
Parameters
----------
width: str = "100%"
height: str = "500px"
fontsize: int = 20
show_occurence: bool = False
"""
html = self._get_html(**kwargs)
doc = escape(html)
self._iframe = (
Expand Down
5 changes: 3 additions & 2 deletions tests/test_fingerprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ def detect(self, res1, res2):

def test_interaction_base(sdf_suppl):
interaction = Dummy()
_repr = repr(interaction)
assert _repr.startswith("<") and ".Dummy at " in _repr
repr_ = repr(interaction)
assert repr_.startswith("<")
assert ".Dummy at " in repr_
assert callable(interaction)
mol = sdf_suppl[0]
metadata = next(interaction.detect(mol, mol))
Expand Down

0 comments on commit f1fcb31

Please sign in to comment.