Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
c2bb26f
fixed handling of modified residues in protein ligands.
snbolz Jan 13, 2025
fcf8da8
Merge pull request #168 from snbolz/bug/keepmod
mestia Jan 14, 2025
427704d
if the keepmod flag is used, keep modified residues as part of the re…
snbolz Jan 23, 2025
ea15bc3
Merge pull request #169 from snbolz/bug/modres_bs
mestia Jan 23, 2025
0504276
enables the detection of charged functional groups in modified residues.
snbolz Jan 23, 2025
1876230
Merge pull request #170 from snbolz/bug/modres_charged
mestia Jan 24, 2025
accf551
added handling of pdb files that have TER lines without continuing nu…
snbolz Mar 11, 2025
93f7fbc
Updated Readme (#176)
PhiCMS Apr 10, 2025
54188c9
dev: adding flag pdb_file_was_corrected
CtrlShanya May 8, 2025
1612786
fix: condition for as_string in read_pdb
CtrlShanya May 8, 2025
7797f0f
fix: pdb complex as string source file for visualizer data
CtrlShanya May 13, 2025
d174c65
fix: broken test suite for using PDBComplex
CtrlShanya May 15, 2025
0860903
fix: using pdb file as string for VisualizerData
CtrlShanya May 20, 2025
6041ea3
fix: typo in attribute
CtrlShanya May 20, 2025
d20949c
Update remote.py
vjhaupt May 20, 2025
a900834
Merge branch 'development' into bugfix/load-pdb-as-string-fix
vjhaupt May 20, 2025
eda5482
Merge pull request #178 from CtrlShanya/bugfix/load-pdb-as-string-fix
vjhaupt May 20, 2025
0f39424
Fix for #186, #185
PhiCMS Jun 19, 2025
e3e7121
fix: missing attribute (#181)
CtrlShanya Jun 20, 2025
d50e3ed
new regions feature to detect interactions between protein regions (e…
snbolz Oct 13, 2025
062d7c5
improved --regions argument parsing for tuples with only one entry.
snbolz Oct 15, 2025
d18a355
Add pyproject.toml, courtesy Nikitas Rontsis, nrontsis@gmail.com
Oct 16, 2025
9bdf35d
Drop requirements.txt
Oct 16, 2025
871ef56
Update pyproject.toml, adjust build system to use setup.py
Oct 16, 2025
6d5f718
hardocde verion, since ./plip is not available while building module
Oct 16, 2025
86cccd5
Update Dockerfile, drop python3-distutils Debian package
Oct 16, 2025
67d5d5d
Merge branch 'development' into feature/domains
mestia Oct 16, 2025
864551f
citation information update to latest PLIP publication.
snbolz Oct 16, 2025
9132b5c
Merge pull request #188 from snbolz/feature/domains
mestia Oct 16, 2025
df921f8
Merge branch 'development' into bug/ter_lines
mestia Oct 16, 2025
6744681
Merge pull request #172 from snbolz/bug/ter_lines
mestia Oct 16, 2025
0f0f651
Merge branch 'development' into chore/update-citation
mestia Oct 16, 2025
7573f04
Merge pull request #191 from snbolz/chore/update-citation
mestia Oct 16, 2025
e422d72
More control about report filename parsing, new default report naming…
snbolz Oct 23, 2025
7ee10a8
Merge pull request #192 from snbolz/feature/report-filename
mestia Oct 23, 2025
87a7e6d
Merge branch 'development' into module_packaging
mestia Oct 23, 2025
35a06d9
Merge pull request #193 from mestia/module_packaging
mestia Oct 24, 2025
ee5a096
update CHANGES.txt
snbolz Oct 27, 2025
b49cc44
Merge pull request #194 from snbolz/chore/update-changelog
mestia Oct 27, 2025
39f0484
Version 3.0.0
Oct 27, 2025
017a4e3
Version 3.0.0
Oct 27, 2025
3327e8a
Merge branch 'master' into development
Oct 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,6 @@ target/
# Other
*~
.nfs*
tests/
tests/
# JetBrains IDE settings
.idea/
10 changes: 10 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
Changelog
---------
# 3.0.0
* added new `--regions` flag to enable detection of interactions between protein regions (by @snbolz)
* reworked XML and TXT report file naming; changes default behavior
* introduced pyproject.toml to ensure compliance with Python packaging standards
* updated Dockerfile
* fixed switched coordinates of halogen bond acceptor and donor atoms
* fixed handling of PDB input passed as string
* fixed handling of modified residues in protein and peptide ligands
* several minor bug fixes

# 2.4.0
* new "--chains" flag to enable detection of interactions between protein chains by @PhiCMS and @snbolz
* update setup.py, attempt to fix and install broken python openbabel bindings 3.1.1.1
Expand Down
12 changes: 7 additions & 5 deletions plip/basic/config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
__version__ = '2.4.0'
__version__ = '3.0.0'
__maintainer__ = 'PharmAI GmbH (2020-2021) - www.pharm.ai - hello@pharm.ai'
__citation_information__ = "Adasme,M. et al. PLIP 2021: expanding the scope of the protein-ligand interaction profiler to DNA and RNA. " \
"Nucl. Acids Res. (05 May 2021), gkab294. doi: 10.1093/nar/gkab294"
__citation_information__ = "Schake,P. Bolz,SN. et al. PLIP 2025: introducing protein–protein interactions to the proteinligand interaction profiler. " \
"Nucl. Acids Res. (10 May 2025), gkaf361. doi: 10.1093/nar/gkaf361"

import logging

Expand All @@ -28,11 +28,13 @@
RESIDUES = {}
KEEPMOD = False
DNARECEPTOR = False
OUTPUTFILENAME = "report" # Naming for the TXT and XML report files
OUTPUTFILENAME = None # Naming for the TXT and XML report files
NOPDBCANMAP = False # Skip calculation of mapping canonical atom order: PDB atom order
NOHYDRO = False # Do not add hydrogen bonds (in case already present in the structure)
MODEL = 1 # The model to be selected for multi-model structures (default = 1).
CHAINS = None # Define chains for protein-protein interaction detection
CHAINS = None # Define chains for protein-protein interaction detection
REGIONS = None
COMPRESS = False # Compress XML and TXT report files


# Configuration file for Protein-Ligand Interaction Profiler (PLIP)
Expand Down
3 changes: 2 additions & 1 deletion plip/basic/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ def __init__(self, mol, site):

# General Information
self.lig_members = sorted(pli.ligand.members)
self.sourcefile = pcomp.sourcefiles['pdbcomplex']
self.source_pdb_file_content = pcomp.sourcefiles['pdbstring'] # store pdb file content as string
self.corrected_pdb = pcomp.corrected_pdb
self.pdbid = mol.pymol_name
self.hetid = ligand.hetid
self.ligandtype = ligand.type
self.regions = ligand.regions
self.chain = ligand.chain if not ligand.chain == "0" else "" # #@todo Fix this
self.position = str(ligand.position)
self.uid = ":".join([self.hetid, self.chain, self.position])
Expand Down
42 changes: 38 additions & 4 deletions plip/basic/supplemental.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,29 @@ def whichchain(atom):
return atom.GetResidue().GetChain() if atom.GetResidue() is not None else None


def residue_belongs_to_receptor(res, config):
def residue_belongs_to_receptor(res, regions=None):
"""tests whether the residue is defined as receptor and is not part of a peptide or residue ligand."""
if config.CHAINS:
if regions:
ligand_region, bs_region = regions
chain = res.GetChain()
num = res.GetNum()
if ligand_region and bs_region: # both ligand and receptor region were defined
if num in ligand_region.get(chain, []):
return False # residue belongs to ligand
if num in bs_region.get(chain, []):
return True # residue belongs to receptor and not to ligand
return False
else:
return num not in ligand_region.get(chain, [])

elif config.CHAINS:
if config.CHAINS[0] and config.CHAINS[1]: # if receptor and ligand chains were given
return res.GetChain() in config.CHAINS[0] and res.GetChain() not in config.CHAINS[1]
# True if residue is part of receptor chains and not of ligand chains
if config.CHAINS[1]: # if only ligand chains were given
return res.GetChain() not in config.CHAINS[1] # True if residue is not part of ligand chains
return False # if only receptor chains were given or both is empty

return res.GetChain() not in config.PEPTIDES # True if residue is not part of peptide ligand.


Expand Down Expand Up @@ -184,9 +198,17 @@ def cluster_doubles(double_list):
# File operations
#################

def tilde_expansion(folder_path):
def tilde_expansion(folder_paths):
"""Tilde expansion, i.e. converts '~' in paths into <value of $HOME>."""
return os.path.expanduser(folder_path) if '~' in folder_path else folder_path
if isinstance(folder_paths, list):
expanded_paths = []
for p in folder_paths:
if "~" in p:
p = os.path.expanduser(p)
expanded_paths.append(p)
return expanded_paths
else:
return os.path.expanduser(folder_paths) if "~" in folder_paths else folder_paths


def folder_exists(folder_path):
Expand Down Expand Up @@ -231,6 +253,18 @@ def start_pymol(quiet=False, options='-p', run=False):
pymol.cmd.feedback('disable', 'all', 'everything')


def select_region(region):
"""region is a dictionary with chains as keys and a list of residue numbers as values."""
selection = f"(chain "
for i, (chain, res_numbers) in enumerate(region.items()):
selection += f"{chain} and not resn HOH and resi {'+'.join(map(str, res_numbers))}"
if not i == len(region) - 1:
selection += ") or (chain "
else:
selection += ")"
return selection


def nucleotide_linkage(residues):
"""Support for DNA/RNA ligands by finding missing covalent linkages to stitch DNA/RNA together."""

Expand Down
26 changes: 19 additions & 7 deletions plip/exchange/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from operator import itemgetter

import lxml.etree as et
import gzip

from plip.basic import config
from plip.basic.config import __version__
Expand Down Expand Up @@ -91,20 +92,31 @@ def get_bindingsite_data(self):
else:
self.txtreport.append('No interactions detected.')

def write_xml(self, as_string=False):
def write_xml(self, as_string: bool = False):
"""Write the XML report"""
if not as_string:
et.ElementTree(self.xmlreport).write('{}/{}.xml'.format(self.outpath, self.outputprefix), pretty_print=True,
xml_declaration=True)
tree = et.ElementTree(self.xmlreport)
if config.COMPRESS:
with gzip.open(f"{self.outpath}{self.outputprefix}.xml.gz", "wb") as xml_file:
tree.write(xml_file, pretty_print=True, xml_declaration=True, encoding="utf-8")
else:
tree.write(f"{self.outpath}{self.outputprefix}.xml", pretty_print=True, xml_declaration=True,
encoding="utf-8")
else:
output = et.tostring(self.xmlreport, pretty_print=True)
print(output.decode('utf8'))

def write_txt(self, as_string=False):
def write_txt(self, as_string: bool = False):
"""Write the TXT report"""
if not as_string:
with open('{}/{}.txt'.format(self.outpath, self.outputprefix), 'w') as f:
[f.write(textline + '\n') for textline in self.txtreport]
if config.COMPRESS:
with gzip.open(f"{self.outpath}{self.outputprefix}.txt.gz", "wb") as txt_file:
for textline in self.txtreport:
txt_file.write((textline + '\n').encode('utf-8'))
else:
with open(f"{self.outpath}{self.outputprefix}.txt", 'w') as txt_file:
for textline in self.txtreport:
txt_file.write(textline + '\n')
else:
output = '\n'.join(self.txtreport)
print(output)
Expand Down Expand Up @@ -280,7 +292,7 @@ def __init__(self, plcomplex):
'%.2f' % halogen.distance, '%.2f' % halogen.don_angle, '%.2f' % halogen.acc_angle,
halogen.don_orig_idx, halogen.donortype,
halogen.acc_orig_idx, halogen.acctype,
halogen.acc.o.coords, halogen.don.x.coords))
halogen.don.x.coords, halogen.acc.o.coords))

###################
# METAL COMPLEXES #
Expand Down
Loading
Loading