[med-svn] [Git][med-team/plip][upstream] New upstream version 2.3.0+dfsg

Alexandre Mestiashvili (@mestia) gitlab at salsa.debian.org
Mon Sep 4 18:10:47 BST 2023



Alexandre Mestiashvili pushed to branch upstream at Debian Med / plip


Commits:
3628dbef by Alexandre Mestiashvili at 2023-08-31T17:13:54+02:00
New upstream version 2.3.0+dfsg
- - - - -


7 changed files:

- CHANGES.txt
- README.md
- plip/basic/config.py
- plip/basic/supplemental.py
- plip/structure/preparation.py
- + plip/test/test_salt_bridges.py
- plip/visualization/pymol.py


Changes:

=====================================
CHANGES.txt
=====================================
@@ -1,5 +1,10 @@
 Changelog
 ---------
+# 2.3.0
+* fixes an issue that caused encoding errors to be thrown
+* salt bridge interaction improved
+* minor bugs fixed
+
 # 2.2.2
 * fixes an issue that caused encoding errors to be thrown
 


=====================================
README.md
=====================================
@@ -69,7 +69,7 @@ If you cannot use the containerized bundle or want to use PLIP sources, make sur
 - Python >= 3.6.9
 - [OpenBabel](#Installing-OpenBabel) >= 3.0.0 with [Python bindings](https://open-babel.readthedocs.io/en/latest/UseTheLibrary/PythonInstall.html)
 - PyMOL >= 2.3.0 with Python bindings (optional, for visualization only)
-- ImageMagick >= 6.9 (optional)
+- ImageMagick >= 7.0 (optional)
 
 **Python:** If you are on a system where Python 3 is executed using `python3` instead of just `python`, replace the `python` and `pip` commands in the following steps with `python3` and `pip3` accordingly.
 
@@ -164,7 +164,7 @@ Using PLIP in your commercial or non-commercial project is generally possible wh
 If you are using PLIP in your work, please cite
 > 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
- 
+
 or
 
 > Salentin,S. et al. PLIP: fully automated protein-ligand interaction profiler.


=====================================
plip/basic/config.py
=====================================
@@ -1,4 +1,4 @@
-__version__ = '2.2.2'
+__version__ = '2.3.0'
 __maintainer__ = 'PharmAI GmbH (2020-2021) - www.pharm.ai - hello at 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"


=====================================
plip/basic/supplemental.py
=====================================
@@ -298,7 +298,6 @@ def sort_members_by_importance(members):
     main = [x for x in members if x[0] not in config.METAL_IONS]
     ion = [x for x in members if x[0] in config.METAL_IONS]
     sorted_main = sorted(main, key=lambda x: (x[1], x[2]))
-    sorted_main = sorted(main, key=lambda x: (x[1], x[2]))
     sorted_ion = sorted(ion, key=lambda x: (x[1], x[2]))
     return sorted_main + sorted_ion
 


=====================================
plip/structure/preparation.py
=====================================
@@ -51,14 +51,16 @@ class PDBParser:
         alt = []
         previous_ter = False
 
-        model_dict = {1: list()}
+        model_dict = {0: list()}
 
         # Standard without fixing
         if not config.NOFIX:
             if not config.PLUGIN_MODE:
                 lastnum = 0  # Atom numbering (has to be consecutive)
                 other_models = False
-                current_model = 1
+                # Model 0 stores header and similar additional data
+                # or the full file if no MODEL entries exist in the file
+                current_model = 0
                 for line in fil:
                     corrected_line, newnum = self.fix_pdbline(line, lastnum)
                     if corrected_line is not None:
@@ -81,8 +83,11 @@ class PDBParser:
                 try:
                     if other_models:
                         logger.info(f'selecting model {config.MODEL} for analysis')
-                    corrected_pdb = ''.join(model_dict[config.MODEL])
-                    corrected_lines = model_dict[config.MODEL]
+                    corrected_pdb = ''.join(model_dict[0])
+                    corrected_lines = model_dict[0]
+                    if current_model > 0:
+                        corrected_pdb += ''.join(model_dict[config.MODEL])
+                        corrected_lines += model_dict[config.MODEL]
                 except KeyError:
                     corrected_pdb = ''.join(model_dict[1])
                     corrected_lines = model_dict[1]
@@ -924,6 +929,7 @@ class BindingSite(Mol):
 
     def find_charged(self, mol):
         """Looks for positive charges in arginine, histidine or lysine, for negative in aspartic and glutamic acid."""
+        """If nucleic acids are part of the receptor, looks for negative charges in phosphate backbone"""
         data = namedtuple('pcharge', 'atoms atoms_orig_idx type center restype resnr reschain')
         a_set = []
         # Iterate through all residue, exclude those in chains defined as peptides
@@ -961,6 +967,17 @@ class BindingSite(Mol):
                                       restype=res.GetName(),
                                       resnr=res.GetNum(),
                                       reschain=res.GetChain()))
+            if res.GetName() in config.DNA + config.RNA and config.DNARECEPTOR: # nucleic acids have negative charge in sugar phosphate
+                for a in pybel.ob.OBResidueAtomIter(res):
+                    if a.GetType().startswith('P') and res.GetAtomProperty(a, 9) \
+                            and not self.Mapper.mapid(a.GetIdx(), mtype='protein') in self.altconf:
+                        a_contributing.append(pybel.Atom(a))
+                        a_contributing_orig_idx.append(self.Mapper.mapid(a.GetIdx(), mtype='protein'))
+                if not len(a_contributing) == 0:
+                    a_set.append(data(atoms=a_contributing,atoms_orig_idx=a_contributing_orig_idx, type='negative', 
+                                      center=centroid([ac.coords for ac in a_contributing]), restype=res.GetName(),
+                                      resnr=res.GetNum(),
+                                      reschain=res.GetChain()))
         return a_set
 
     def find_metal_binding(self, mol):
@@ -1365,7 +1382,7 @@ class PDBComplex:
 
         if not as_string:
             self.sourcefiles['filename'] = os.path.basename(self.sourcefiles['pdbcomplex'])
-        self.protcomplex, self.filetype = read_pdb(self.corrected_pdb, as_string=True)
+        self.protcomplex, self.filetype = read_pdb(self.corrected_pdb, as_string= (self.corrected_pdb != pdbpath)) # self.corrected_pdb may fallback to pdbpath
 
         # Update the model in the Mapper class instance
         self.Mapper.original_structure = self.protcomplex.OBMol


=====================================
plip/test/test_salt_bridges.py
=====================================
@@ -0,0 +1,23 @@
+import unittest
+
+from plip.basic import config
+from plip.structure.preparation import PDBComplex, PLInteraction
+
+
+def characterize_complex(pdb_file: str, binding_site_id: str) -> PLInteraction:
+    pdb_complex = PDBComplex()
+    pdb_complex.load_pdb(pdb_file)
+    for ligand in pdb_complex.ligands:
+        if ':'.join([ligand.hetid, ligand.chain, str(ligand.position)]) == binding_site_id:
+            pdb_complex.characterize_complex(ligand)
+    return pdb_complex.interaction_sets[binding_site_id]
+
+class SaltBridgeTest(unittest.TestCase):
+
+    def test_4yb0(self):
+        '''test salt bridge detection for nucleic acids as part of the receptor'''
+
+        config.DNARECEPTOR = True
+        interactions = characterize_complex('./pdb/4yb0.pdb', 'C2E:R:102')
+        salt_bridges = interactions.saltbridge_lneg + interactions.saltbridge_pneg
+        self.assertTrue(len(salt_bridges) == 1)
\ No newline at end of file


=====================================
plip/visualization/pymol.py
=====================================
@@ -363,21 +363,29 @@ class PyMOLVisualizer:
         os.rename(originalfile, newfile)  # Remove frame number in filename
 
         #  Check if imagemagick is available and crop + resize the images
-        if subprocess.call("type convert", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0:
+        if subprocess.call("magick -version", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0:
             attempts, ecode = 0, 1
             # Check if file is truncated and wait if that's the case
             while ecode != 0 and attempts <= 10:
-                ecode = subprocess.call(['convert', newfile, '/dev/null'], stdout=open('/dev/null', 'w'),
+                ecode = subprocess.call(['magick', newfile, os.devnull], stdout=open(os.devnull, 'w'),
                                         stderr=subprocess.STDOUT)
                 sleep(0.1)
                 attempts += 1
-            trim = 'convert -trim ' + newfile + ' -bordercolor White -border 20x20 ' + newfile + ';'  # Trim the image
+            trim = f'magick {newfile} -trim -bordercolor White -border 20x20 {newfile}'  # Trim the image
             os.system(trim)
-            getwidth = 'w=`convert ' + newfile + ' -ping -format "%w" info:`;'  # Get the width of the new image
-            getheight = 'h=`convert ' + newfile + ' -ping -format "%h" info:`;'  # Get the hight of the new image
-            newres = 'if [ "$w" -gt "$h" ]; then newr="${w%.*}x$w"; else newr="${h%.*}x$h"; fi;'  # Set quadratic ratio
-            quadratic = 'convert ' + newfile + ' -gravity center -extent "$newr" ' + newfile  # Fill with whitespace
-            os.system(getwidth + getheight + newres + quadratic)
+            # Get the width of the new image
+            getwidth = f'magick {newfile} -ping -format "%w" info:'
+            w = int(subprocess.run(getwidth, capture_output=True, text=True).stdout)
+            # Get the hight of the new image
+            getheight = f'magick {newfile} -ping -format "%h" info:'
+            h = int(subprocess.run(getheight, capture_output=True, text=True).stdout)
+            # Set quadratic ratio
+            if w > h:
+                newr= f'{w}x{w}'
+            else:
+                newr= f'{h}x{h}'
+            quadratic = f'magick {newfile} -gravity center -extent {newr} {newfile}'  # Fill with whitespace
+            os.system(quadratic)
         else:
             sys.stderr.write('Imagemagick not available. Images will not be resized or cropped.')
 



View it on GitLab: https://salsa.debian.org/med-team/plip/-/commit/3628dbef837a3b2015d959a9233a51806ffc747c

-- 
View it on GitLab: https://salsa.debian.org/med-team/plip/-/commit/3628dbef837a3b2015d959a9233a51806ffc747c
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20230904/1693a9f4/attachment-0001.htm>


More information about the debian-med-commit mailing list