[med-svn] [Git][med-team/plip][master] 10 commits: New upstream version 2.1.5+dfsg

Nilesh Patra gitlab at salsa.debian.org
Tue Nov 10 07:22:55 GMT 2020



Nilesh Patra pushed to branch master at Debian Med / plip


Commits:
e8f1daf1 by Nilesh Patra at 2020-11-10T07:17:33+00:00
New upstream version 2.1.5+dfsg
- - - - -
29d969f2 by Nilesh Patra at 2020-11-10T07:17:33+00:00
routine-update: New upstream version

- - - - -
501ce9a0 by Nilesh Patra at 2020-11-10T07:17:34+00:00
Update upstream source from tag 'upstream/2.1.5+dfsg'

Update to upstream version '2.1.5+dfsg'
with Debian dir 845e2e866749f53faec638c88ccd279f85c7f927
- - - - -
09bfd4f4 by Nilesh Patra at 2020-11-10T07:17:35+00:00
routine-update: debhelper-compat 13

- - - - -
000720dd by Nilesh Patra at 2020-11-10T07:17:44+00:00
routine-update: Add salsa-ci file

- - - - -
428b943c by Nilesh Patra at 2020-11-10T07:17:44+00:00
routine-update: Rules-Requires-Root: no

- - - - -
dd7cdc21 by Nilesh Patra at 2020-11-10T07:17:59+00:00
Set field Upstream-Contact in debian/copyright.

Changes-By: lintian-brush

- - - - -
78d8497a by Nilesh Patra at 2020-11-10T07:18:16+00:00
Set upstream metadata fields: Bug-Database, Bug-Submit, Repository, Repository-Browse.

Changes-By: lintian-brush
Fixes: lintian: upstream-metadata-missing-bug-tracking
See-also: https://lintian.debian.org/tags/upstream-metadata-missing-bug-tracking.html
Fixes: lintian: upstream-metadata-missing-repository
See-also: https://lintian.debian.org/tags/upstream-metadata-missing-repository.html

- - - - -
637b060b by Nilesh Patra at 2020-11-10T07:18:16+00:00
Remove obsolete fields Contact, Name from debian/upstream/metadata (already present in machine-readable debian/copyright).

Changes-By: lintian-brush

- - - - -
43291b9a by Nilesh Patra at 2020-11-10T07:18:17+00:00
routine-update: Ready to upload to unstable

- - - - -


15 changed files:

- CHANGES.txt
- DOCUMENTATION.md
- README.md
- debian/changelog
- debian/control
- debian/copyright
- + debian/salsa-ci.yml
- debian/upstream/metadata
- plip/basic/config.py
- plip/exchange/webservices.py
- plip/plipcmd.py
- plip/structure/preparation.py
- plip/test/test_basic_functions.py
- plip/test/test_remote_services.py
- + plip/test/test_structure_processing.py


Changes:

=====================================
CHANGES.txt
=====================================
@@ -1,9 +1,8 @@
 Changelog
 ---------
-# 2.2.0
-* bug fixes in code and deployment
-* multi-architecture builds on https://hub.docker.com/r/pharmai/plip
-* Docker build for Ubuntu 20.04 LTS
+# 2.1.5
+* option added to handle specific model in NMR structures
+* fixes a bug in alt-location handling
 
 # 2.1.0
 * maintainer changed to PharmAI GmbH
@@ -16,6 +15,9 @@ Changelog
 * adds option to disable non-deterministic protonation of structures (`--nohydro`)
 * protonated structures are now stored to guarantee consistent interaction detection
 * new options to change verbosity levels
+* bug fixes in code and deployment
+* multi-architecture builds on https://hub.docker.com/r/pharmai/plip
+* Docker build for Ubuntu 20.04 LTS
 
 # 1.4.5
 * Updates contact info


=====================================
DOCUMENTATION.md
=====================================
@@ -102,7 +102,7 @@ PLIP will create subdirectories for each given structure in the output folder. I
 For the detection of ligands, PLIP relies on the separation of `ATOM` and `HETATM` entries in the PDB file. The latter are searched for suitable ligands when running in normal mode. Peptide ligands, however, are usually deposited as `ATOM` entries in a separate chain. PLIP can not detect these entities automatically. To switch into protein-peptide interaction mode, start PLIP with the option `--peptide`, followed by the peptide chain of interest, e.g.:
 
 ```bash
-$ plip -i 5hi4 --peptides I -vx
+$ plip -i 5hi4 --peptide I -vx
 ```
 
 ### Detection of Intra-Chain Interactions
@@ -142,6 +142,7 @@ PLIP offers further command line options which enables you to switch advanced se
 - Turn off automatic fixing of errors in PDB files (`--nofix`)
 - Keep modified residues as ligands (`--keepmod`)
 - Do not protonate structures with non-deterministic OpenBabel routines (`--nohydro`)
+- Select a specific model from an ensemble structure (`--model`)
 
 ## Web Service
 A web service for analysis of protein-ligand complexes using PLIP is available at
@@ -376,4 +377,4 @@ metal_complex | coordination | Metal coordination number |
 metal_complex | location | Location of the target group |
 metal_complex | rms | RMS of the geometry fit |
 metal_complex | geometry | Metal coordination type |
-metal_complex | complexnum | Continous numbering for the metal complex |
\ No newline at end of file
+metal_complex | complexnum | Continous numbering for the metal complex |


=====================================
README.md
=====================================
@@ -13,11 +13,13 @@ Analyze noncovalent protein-ligand interactions in 3D structures with ease.
 
 | Use Case                                                                  | [Web Server](https://projects.biotec.tu-dresden.de/plip-web/plip)         | Docker             | Singularity        | Python Module       |
 |---------------------------------------------------------------------------|--------------------|--------------------|--------------------|--------------------|
-| "I want to analyze my protein-ligand complex!"                            | :heavy_check_mark: | :yellow_circle:    | :yellow_circle:    | :x:                |
-| "I want to analyze *a billion* protein-ligand complexes!"                   | :x:                | :yellow_circle:    | :heavy_check_mark: | :yellow_circle:    |
-| "I love the Linux command line and want to build a workflow around PLIP!" | :x:    | :heavy_check_mark: | :heavy_check_mark: | :yellow_circle:    |
+| "I want to analyze my protein-ligand complex!"                            | :heavy_check_mark: | :heavy_check_mark: | :yellow_circle:    | :x:                |
+| "I want to analyze *a billion* protein-ligand complexes!"                 | :x:                | :yellow_circle:    | :heavy_check_mark: | :yellow_circle:    |
+| "I love the Linux command line and want to build a workflow around PLIP!" | :x:                | :heavy_check_mark: | :heavy_check_mark: | :yellow_circle:    |
 | "I'm a Python programmer and want to use PLIP in my project!"             | :x:                | :yellow_circle:    | :yellow_circle:    | :heavy_check_mark: |
 
+:exclamation: **Note:** The web server is currently running an outdated version of PLIP, which will be replaced soon. For production use and data analysis we highly recommend to use the current command line release. :exclamation:
+
 ---
 
 ## Quickstart
@@ -59,7 +61,7 @@ For more details, see the [Documentation](DOCUMENTATION.md).
 
 Open a new system terminal and clone this repository using
 ```bash
-$ git clone https://github.com/ssalentin/plip.git ~/pliptool
+$ git clone https://github.com/pharmai/plip.git
 ```
 
 ### 2. Install PLIP
@@ -169,6 +171,10 @@ Due to the non-deterministic nature on how hydrogen atoms can be added to the in
 - protonate the input structure once with PLIP or your tool of preference
 - run PLIP with `--nohydro`
 
+> How does PLIP handle NMR structures?
+>
+By default PLIP uses the first model it sees in a PDB file. You can change this behavior with the flag `--model`.
+
 ## Contact / Maintainer
 As of April 2020 PLIP is now officially maintained by [PharmAI GmbH](https://pharm.ai). Do you have feature requests, found a bug or want to use  PLIP in your project? Commercial support is available upon request.
 


=====================================
debian/changelog
=====================================
@@ -1,3 +1,13 @@
+plip (2.1.5+dfsg-1) unstable; urgency=medium
+
+  * Team upload.
+  * New upstream version
+  * debhelper-compat 13 (routine-update)
+  * Add salsa-ci file (routine-update)
+  * Rules-Requires-Root: no (routine-update)
+
+ -- Nilesh Patra <npatra974 at gmail.com>  Tue, 10 Nov 2020 07:18:16 +0000
+
 plip (2.1.4+dfsg-2) unstable; urgency=medium
 
   * No change, source-only upload to allow testing migration.


=====================================
debian/control
=====================================
@@ -3,7 +3,7 @@ Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.
 Uploaders: Alexandre Mestiashvili <mestia at debian.org>
 Section: python
 Priority: optional
-Build-Depends: debhelper-compat (= 12),
+Build-Depends: debhelper-compat (= 13),
                dh-python,
                help2man,
                python3-all,
@@ -16,6 +16,7 @@ Standards-Version: 4.5.0
 Vcs-Browser: https://salsa.debian.org/med-team/plip
 Vcs-Git: https://salsa.debian.org/med-team/plip.git
 Homepage: https://projects.biotec.tu-dresden.de/plip-web/plip/
+Rules-Requires-Root: no
 
 Package: plip
 Architecture: all


=====================================
debian/copyright
=====================================
@@ -10,6 +10,7 @@ Files-Excluded:
   Dockerfile*
   plip/__pycache__
   build_multi.sh
+Upstream-Contact: Sebastian Salentin <sebastian.salentin at biotec.tu-dresden.de>
 
 Files: *
 Copyright: 2016 Sebastian Salentin <sebastian.salentin at biotec.tu-dresden.de>


=====================================
debian/salsa-ci.yml
=====================================
@@ -0,0 +1,4 @@
+---
+include:
+  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
+  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml


=====================================
debian/upstream/metadata
=====================================
@@ -1,5 +1,5 @@
-Contact: Sebastian Salentin <sebastian.salentin at biotec.tu-dresden.de>
-Name: plip
+Bug-Database: https://github.com/ssalentin/plip/issues
+Bug-Submit: https://github.com/ssalentin/plip/issues/new
 Cite-As: "Salentin, S. et al. PLIP: fully automated protein-ligand \
  interaction profiler. Nucl. Acids Res. first published online April 14, \
  2015 doi:10.1093/nar/gkv315"
@@ -25,3 +25,5 @@ Registry:
    Entry: plip
  - Name: conda:bioconda
    Entry: NA
+Repository: https://github.com/ssalentin/plip.git
+Repository-Browse: https://github.com/ssalentin/plip


=====================================
plip/basic/config.py
=====================================
@@ -1,4 +1,4 @@
-__version__ = '2.1.4'
+__version__ = '2.1.5'
 __maintainer__ = 'PharmAI GmbH (2020) - www.pharm.ai - hello at pharm.ai'
 
 import logging
@@ -28,6 +28,7 @@ DNARECEPTOR = False
 OUTPUTFILENAME = "report"  # 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).
 
 # Configuration file for Protein-Ligand Interaction Profiler (PLIP)
 # Set thresholds for detection of interactions


=====================================
plip/exchange/webservices.py
=====================================
@@ -28,19 +28,20 @@ def fetch_pdb(pdbid):
     """Get the newest entry from the RCSB server for the given PDB ID. Exits with '1' if PDB ID is invalid."""
     pdbid = pdbid.lower()
     logger.info(f'checking status of PDB-ID {pdbid}')
-    state, current_entry = check_pdb_status(pdbid)  # Get state and current PDB ID
-
-    if state == 'OBSOLETE':
-        logger.info(f'entry is obsolete, getting {current_entry} instead')
-    elif state == 'CURRENT':
-        logger.info('entry is up-to-date')
-    elif state == 'UNKNOWN':
-        logger.error('invalid PDB-ID (entry does not exist on PDB server)')
-        sys.exit(1)
+    # @todo re-implement state check with ew RCSB API, see https://www.rcsb.org/news?year=2020&article=5eb18ccfd62245129947212a&feature=true
+    # state, current_entry = check_pdb_status(pdbid)  # Get state and current PDB ID
+    #
+    # if state == 'OBSOLETE':
+    #     logger.info(f'entry is obsolete, getting {current_entry} instead')
+    # elif state == 'CURRENT':
+    #     logger.info('entry is up-to-date')
+    # elif state == 'UNKNOWN':
+    #     logger.error('invalid PDB-ID (entry does not exist on PDB server)')
+    #     sys.exit(1)
     logger.info('downloading file from PDB')
     # get URL for current entry
     # @todo needs update to react properly on response codes of RCSB servers
-    pdburl = f'http://www.rcsb.org/pdb/files/{current_entry}.pdb'
+    pdburl = f'http://www.rcsb.org/pdb/files/{pdbid}.pdb'
     try:
         pdbfile = urlopen(pdburl).read().decode()
         # If no PDB file is available, a text is now shown with "We're sorry, but ..."
@@ -51,4 +52,4 @@ def fetch_pdb(pdbid):
     except HTTPError:
         logger.error('no file in PDB format available from wwPDB for the given PDB ID')
         sys.exit(1)
-    return [pdbfile, current_entry]
+    return [pdbfile, pdbid]


=====================================
plip/plipcmd.py
=====================================
@@ -225,6 +225,9 @@ def main():
     parser.add_argument("--nohydro", dest="nohydro", default=False,
                         help="Do not add polar hydrogens in case your structure already contains hydrogens.",
                         action="store_true")
+    parser.add_argument("--model", dest="model", default=1,
+                        help="Model number to be used for multi-model structures.",
+                        action="store_true")
     # Optional threshold arguments, not shown in help
     thr = namedtuple('threshold', 'name type')
     thresholds = [thr(name='aromatic_planarity', type='angle'),
@@ -275,6 +278,7 @@ def main():
     config.DNARECEPTOR = arguments.dnareceptor
     config.OUTPUTFILENAME = arguments.outputfilename
     config.NOHYDRO = arguments.nohydro
+    config.MODEL = arguments.model
     # Make sure we have pymol with --pics and --pymol
     if config.PICS or config.PYMOL:
         try:


=====================================
plip/structure/preparation.py
=====================================
@@ -51,25 +51,39 @@ class PDBParser:
         alt = []
         previous_ter = False
 
+        model_dict = {1: 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
                 for line in fil:
-                    if not other_models:  # Only consider the first model in an NRM structure
-                        corrected_line, newnum = self.fix_pdbline(line, lastnum)
-                        if corrected_line is not None:
-                            if corrected_line.startswith('MODEL'):
-                                try:  # Get number of MODEL (1,2,3)
-                                    model_num = int(corrected_line[10:14])
-                                    if model_num > 1:  # MODEL 2,3,4 etc.
-                                        other_models = True
-                                except ValueError:
-                                    logger.debug(f'ignoring invalid MODEL entry: {corrected_line}')
-                            corrected_lines.append(corrected_line)
-                            lastnum = newnum
-                corrected_pdb = ''.join(corrected_lines)
+                    corrected_line, newnum = self.fix_pdbline(line, lastnum)
+                    if corrected_line is not None:
+                        if corrected_line.startswith('MODEL'):
+                            try:  # Get number of MODEL (1,2,3)
+                                model_num = int(corrected_line[10:14])
+                                # initialize storage for new model
+                                model_dict[model_num] = list()
+                                current_model = model_num
+                                if model_num > 1:  # MODEL 2,3,4 etc.
+                                    other_models = True
+                            except ValueError:
+                                logger.debug(f'ignoring invalid MODEL entry: {corrected_line}')
+                        lastnum = newnum
+                        model_dict[current_model].append(corrected_line)
+                # select model
+                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]
+                except KeyError:
+                    corrected_pdb = ''.join(model_dict[1])
+                    corrected_lines = model_dict[1]
+                    logger.warning('invalid model number specified, using first model instead')
             else:
                 corrected_pdb = self.pdbpath
                 corrected_lines = fil
@@ -295,15 +309,16 @@ class LigandFinder:
             cur_hetatoms = {obatom.GetIdx(): obatom for obatom in pybel.ob.OBResidueAtomIter(obresidue) if
                             obatom.GetAtomicNum() != 1}
             if not config.ALTLOC:
-                # Remove alternative conformations (standard -> True)
-                ids_to_remove = [atom_id for atom_id in hetatoms.keys() if
+                # remove alternative conformations (standard -> True)
+                ids_to_remove = [atom_id for atom_id in cur_hetatoms.keys() if
                                  self.mapper.mapid(atom_id, mtype='protein', to='internal') in self.altconformations]
                 for atom_id in ids_to_remove:
                     del cur_hetatoms[atom_id]
             hetatoms.update(cur_hetatoms)
         logger.debug(f'hetero atoms determined (n={len(hetatoms)})')
 
-        lig = pybel.ob.OBMol()  # new ligand mol
+        # create a new ligand molecule representing any k-mer linked structures
+        lig = pybel.ob.OBMol()
         neighbours = dict()
         for obatom in hetatoms.values():  # iterate over atom objects
             idx = obatom.GetIdx()


=====================================
plip/test/test_basic_functions.py
=====================================
@@ -4,15 +4,16 @@ Protein-Ligand Interaction Profiler - Analyze and visualize protein-ligand inter
 test_basic_functions.py - Unit Tests for basic functionality.
 """
 
+import random
 # Python Standard Library
 import unittest
+
 import numpy
-import random
 
-# Own modules
-from plip.structure.preparation import PDBComplex
 from plip.basic.supplemental import euclidean3d, vector, vecangle, projection
 from plip.basic.supplemental import normalize_vector, cluster_doubles, centroid
+# Own modules
+from plip.structure.preparation import PDBComplex
 
 
 class TestLigandSupport(unittest.TestCase):
@@ -29,6 +30,13 @@ class TestLigandSupport(unittest.TestCase):
                 # DNA only contains four bases
                 self.assertEqual(ligset, {'DG', 'DC', 'DA', 'DT'})
 
+    def test_composite_ligand_alternate_locations(self):
+        pdb_complex = PDBComplex()
+        pdb_complex.load_pdb('./pdb/4gql.pdb')
+        for ligand in pdb_complex.ligands:
+            pdb_complex.characterize_complex(ligand)
+        self.assertEqual(len(pdb_complex.ligands[0].can_to_pdb), 53)
+
 
 class TestMapping(unittest.TestCase):
     """Test"""
@@ -73,7 +81,7 @@ class GeometryTest(unittest.TestCase):
 
     @staticmethod
     def vector_magnitude(v):
-        return numpy.sqrt(sum(x**2 for x in v))
+        return numpy.sqrt(sum(x ** 2 for x in v))
 
     # noinspection PyUnusedLocal
     def setUp(self):


=====================================
plip/test/test_remote_services.py
=====================================
@@ -12,6 +12,7 @@ from plip.exchange.webservices import check_pdb_status
 class TestPDB(unittest.TestCase):
     """Test PDB Web Service methods"""
 
+    @unittest.skip("needs re-implementation to new RCSB API standards")
     def test_pdb_entry_status(self):
         # 1a0v is an obsolete entry and is replaced by 1y46
         status, current_pdbid = check_pdb_status('1a0v')


=====================================
plip/test/test_structure_processing.py
=====================================
@@ -0,0 +1,31 @@
+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 StructureProcessingTestCase(unittest.TestCase):
+    def test_nmr(self):
+        all_hydrogen_bonds = set()
+        for i in range(1, 10):
+            config.MODEL = i
+            interactions = characterize_complex('./pdb/2ndo.pdb', 'SFQ:A:201')
+            all_hbonds = interactions.hbonds_ldon + interactions.hbonds_pdon
+            all_hydrogen_bonds.add(len(all_hbonds))
+        # models contain from 0-2 hydrogen bonds
+        self.assertEquals(all_hydrogen_bonds, {0, 1, 2})
+
+    def test_nmr_invalid_model(self):
+        config.MODEL = 11
+        interactions = characterize_complex('./pdb/2ndo.pdb', 'SFQ:A:201')
+        all_hbonds = interactions.hbonds_ldon + interactions.hbonds_pdon
+        self.assertEquals(len(all_hbonds), 1)



View it on GitLab: https://salsa.debian.org/med-team/plip/-/compare/49d9187ccb42a4078ef5c63a7a09b6c13ff93082...43291b9a3cac609068606ad2906c96baf9825fb1

-- 
View it on GitLab: https://salsa.debian.org/med-team/plip/-/compare/49d9187ccb42a4078ef5c63a7a09b6c13ff93082...43291b9a3cac609068606ad2906c96baf9825fb1
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/20201110/852efc12/attachment-0001.html>


More information about the debian-med-commit mailing list