[med-svn] [Git][med-team/plip][master] 6 commits: New upstream version 1.4.0~b+dfsg
Alexandre Mestiashvili
gitlab at salsa.debian.org
Thu Apr 12 14:57:15 BST 2018
Alexandre Mestiashvili pushed to branch master at Debian Med / plip
Commits:
997353ae by Alexandre Mestiashvili at 2018-04-12T12:05:48+02:00
New upstream version 1.4.0~b+dfsg
- - - - -
f89991ca by Alexandre Mestiashvili at 2018-04-12T12:05:48+02:00
Update upstream source from tag 'upstream/1.4.0_b+dfsg'
Update to upstream version '1.4.0~b+dfsg'
with Debian dir 44455e4a5f9b348df0ea8102b8e4116cca7a94be
- - - - -
e5dcf2eb by Alexandre Mestiashvili at 2018-04-12T12:41:07+02:00
Update d/control, add python-future build-dep, update maintainer email, fix VCS
Bump policy and set debhelper to 11
- - - - -
76c6a3a2 by Alexandre Mestiashvili at 2018-04-12T12:41:49+02:00
Set compat to 11
- - - - -
b1582e00 by Alexandre Mestiashvili at 2018-04-12T12:50:15+02:00
Remove unused lintian override
- - - - -
caf52b10 by Alexandre Mestiashvili at 2018-04-12T12:56:54+02:00
Update changelog
- - - - -
20 changed files:
- CHANGES.txt
- DOCUMENTATION.md
- − TODO.txt
- debian/changelog
- debian/compat
- debian/control
- − debian/plip.lintian-overrides
- plip/modules/config.py
- plip/modules/detection.py
- plip/modules/mp.py
- plip/modules/plipxml.py
- plip/modules/preparation.py
- plip/modules/pymolplip.py
- plip/modules/report.py
- plip/modules/supplemental.py
- plip/modules/visualize.py
- plip/modules/webservices.py
- plip/plipcmd
- plip/test/test_basic_functions.py
- setup.py
Changes:
=====================================
CHANGES.txt
=====================================
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,8 +1,11 @@
Changelog
---------
-### Next version
--
+# 1.4.0
+* __Full Python 3 Compatibility__
+* __Read PDB files from stdin with "-f -" and write to stdout with "-O" (capital "O")__
+* Improves handling of fixed PDB files
+* Option to turn off writing fixed PDB structures to a file ("--nofixfile")
### 1.3.5
* Preparation for Python 3: Imports
=====================================
DOCUMENTATION.md
=====================================
--- a/DOCUMENTATION.md
+++ b/DOCUMENTATION.md
@@ -87,7 +87,7 @@ plip -i 1vsn -v
The command above will fetch the PDB entry 1vsn from the server, analyze all interactions and print out the results (verbose mode).
No output files are produced at this point.
-The same can be done for local PDB files.
+The same can be done for local PDB files (-f <file>) or for reading from stdin (-f -).
```bash
wget http://files.rcsb.org/download/1EVE.pdb
@@ -99,6 +99,7 @@ The output formats can be added in any combination, currently including:
* Text report files (`-t`, human-readable)
* PyMOL session files (`-y`)
* Ray-traced images (`-p`)
+* writing to stdout (`-O`), to be used in combination with XML or text report files
```bash
plip -i 1osn -pyx
@@ -278,7 +279,7 @@ The distance between the other ring center and the projected point (i.e. the off
This value corresponds approximately to the radius of benzene + 0.6 Å.
##### π-Cation Interactions
-π-Cation interactions are reported for each pairing of a positive charge and an aromatic ring if the distance between the charge center and the aromatic ring center is less than PICATION_DIST_MAX.
+π-Cation interactions are reported for each pairing of a positive charge and an aromatic ring if the distance between the charge center and the aromatic ring center is less than PICATION_DIST_MAX and the offset between the ring center and the charge is no larger than PISTACK_OFFSET_MAX.
In the case of a putative π-cation interaction with a tertiary amine of the ligand, an additional angle criterion is applied (see documentation in the source code).
##### Salt Bridges
=====================================
TODO.txt deleted
=====================================
--- a/TODO.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-Possible future features
-========================
-
-* Python 3 support
-* support special characters in filenames (e.g. spanish accents), currently cause problems in XML report
-* support for mmcif format
-* support presets for hydrogenation
-* detection of steric clashes
-* detection of anion-pi interactions
-* detection of electrostatic repulsion force_string
-* detection of Keesom forces
-* weak hydrogen bonding
-* visualization: show hydrogen atoms in PyMOL for hydrogen bonds and adapt interaction vector accordingly
-* use SMARTS for detection of chemical features (charged groups, etc.)
=====================================
debian/changelog
=====================================
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,22 @@
+plip (1.4.0~b+dfsg-1) unstable; urgency=medium
+
+ [ Steffen Möller ]
+ * Updated RRID in d/u/metadata
+
+ [ Andreas Tille ]
+ * Remove invalid fields from debian/upstream/metadata
+
+ [ Alexandre Mestiashvili ]
+ * New upstream version 1.4.0~b+dfsg
+ * Update d/control:
+ - Add python-future build-dep
+ - Update uploader's email
+ - fix VCS-* fields to point to salsa
+ - Set debhelper and compat to 11
+ * Remove unused lintian override
+
+ -- Alexandre Mestiashvili <mestia at debian.org> Thu, 12 Apr 2018 12:51:07 +0200
+
plip (1.3.5+dfsg-1) unstable; urgency=medium
* Bump Standards-Version to 4.1.1
=====================================
debian/compat
=====================================
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-9
+11
=====================================
debian/control
=====================================
--- a/debian/control
+++ b/debian/control
@@ -1,9 +1,9 @@
Source: plip
Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.org>
-Uploaders: Alexandre Mestiashvili <alex at biotec.tu-dresden.de>
+Uploaders: Alexandre Mestiashvili <mestia at debian.org>
Section: python
Priority: optional
-Build-Depends: debhelper (>= 9),
+Build-Depends: debhelper (>= 11),
dh-python,
help2man,
pymol,
@@ -11,10 +11,11 @@ Build-Depends: debhelper (>= 9),
python-lxml,
python-numpy,
python-openbabel,
- python-setuptools
-Standards-Version: 4.1.1
-Vcs-Browser: https://anonscm.debian.org/cgit/debian-med/plip.git
-Vcs-Git: https://anonscm.debian.org/git/debian-med/plip.git
+ python-setuptools,
+ python-future
+Standards-Version: 4.1.3
+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/
Package: plip
=====================================
debian/plip.lintian-overrides deleted
=====================================
--- a/debian/plip.lintian-overrides
+++ /dev/null
@@ -1 +0,0 @@
-plip: spelling-error-in-manpage
=====================================
plip/modules/config.py
=====================================
--- a/plip/modules/config.py
+++ b/plip/modules/config.py
@@ -10,12 +10,15 @@ XML = False
TXT = False
PICS = False
PYMOL = False
+STDOUT = False
+RAWSTRING = False # use raw strings for input / output
OUTPATH = './'
BASEPATH = './'
BREAKCOMPOSITE = False # Break up composite ligands with covalent bonds
ALTLOC = False # Consider alternate locations
PLUGIN_MODE = False # Special mode for PLIP in Plugins (e.g. PyMOL)
NOFIX = False # Turn off fixing of errors in PDB files
+NOFIXFILE = False # Turn off writing to files for fixed PDB structures
PEPTIDES = [] # Definition which chains should be considered as peptide ligands
INTRA = None
KEEPMOD = False
=====================================
plip/modules/detection.py
=====================================
--- a/plip/modules/detection.py
+++ b/plip/modules/detection.py
@@ -9,8 +9,8 @@ import itertools
from collections import defaultdict
# Own modules
-from plip.modules.supplemental import *
-import plip.modules.config
+from .supplemental import *
+from . import config
def filter_contacts(pairings):
=====================================
plip/modules/mp.py
=====================================
--- a/plip/modules/mp.py
+++ b/plip/modules/mp.py
@@ -5,6 +5,7 @@ mp.py - Functions for parallel processing
# Python Standard Library
from __future__ import division
+from builtins import zip
import multiprocessing
import itertools
from numpy import asarray
@@ -28,7 +29,7 @@ def universal_worker(input_pair):
def pool_args(function, sequence, kwargs):
"""Return a single iterator of n elements of lists of length 3, given a sequence of len n."""
- return itertools.izip(itertools.repeat(function), sequence, itertools.repeat(kwargs))
+ return zip(itertools.repeat(function), sequence, itertools.repeat(kwargs))
def parallel_fn(f):
=====================================
plip/modules/plipxml.py
=====================================
--- a/plip/modules/plipxml.py
+++ b/plip/modules/plipxml.py
@@ -9,7 +9,11 @@ from lxml import etree
import itertools
from itertools import groupby
import sys
-import urllib2
+
+try: # Python 3
+ from urllib.request import urlopen
+except ImportError: # Fallback Python 2.x
+ from urllib2 import urlopen
class XMLStorage:
@@ -190,6 +194,7 @@ class BSite(XMLStorage):
self.longname = self.getdata(bindingsite, 'identifiers/longname')
self.ligtype = self.getdata(bindingsite, 'identifiers/ligtype')
self.smiles = self.getdata(bindingsite, 'identifiers/smiles')
+ self.inchikey = self.getdata(bindingsite, 'identifiers/inchikey')
# Information on binding site members
self.members = []
@@ -298,7 +303,7 @@ class PLIPXMLREST(PLIPXML):
def load_data(self, pdbid):
"""Loads and parses an XML resource and saves it as a tree if successful"""
#TODO Implement error handling
- f = urllib2.urlopen("http://projects.biotec.tu-dresden.de/plip-rest/pdb/%s?format=xml" % pdbid.lower())
+ f = urlopen("http://projects.biotec.tu-dresden.de/plip-rest/pdb/%s?format=xml" % pdbid.lower())
try:
self.doc = etree.parse(f)
except IOError:
=====================================
plip/modules/preparation.py
=====================================
--- a/plip/modules/preparation.py
+++ b/plip/modules/preparation.py
@@ -6,12 +6,13 @@ preparation.py - Prepare PDB input files for processing.
# Python Standard Library
from __future__ import absolute_import
+from builtins import filter
from operator import itemgetter
# Own modules
-from plip.modules.detection import *
-from plip.modules.supplemental import *
-import plip.modules.config
+from .detection import *
+from .supplemental import *
+from . import config
################
@@ -37,10 +38,11 @@ class PDBParser:
IV. Alternative conformations
"""
if self.as_string:
- fil = self.pdbpath.split('\n')
+ fil = self.pdbpath.rstrip('\n').split('\n') # Removing trailing newline character
else:
- fil = read(self.pdbpath).readlines()
- # #@todo Also consider SSBOND entries here
+ f = read(self.pdbpath)
+ fil = f.readlines()
+ f.close()
corrected_lines = []
i, j = 0, 0 # idx and PDB numbering
d = {}
@@ -75,7 +77,6 @@ class PDBParser:
corrected_pdb = self.pdbpath
corrected_lines = fil
-
for line in corrected_lines:
if line.startswith(("ATOM", "HETATM")):
# Retrieve alternate conformations
@@ -293,7 +294,7 @@ class LigandFinder:
hetatoms = set()
for obresidue in kmer:
hetatoms_res = set([(obatom.GetIdx(), obatom) for obatom in pybel.ob.OBResidueAtomIter(obresidue)
- if not obatom.IsHydrogen()])
+ if obatom.GetAtomicNum() != 1])
if not config.ALTLOC:
# Remove alternative conformations (standard -> True)
@@ -488,7 +489,7 @@ class Mol:
"""Find all possible hydrogen bond acceptors"""
data = namedtuple('hbondacceptor', 'a a_orig_atom a_orig_idx type')
a_set = []
- for atom in itertools.ifilter(lambda at: at.OBAtom.IsHbondAcceptor(), all_atoms):
+ for atom in filter(lambda at: at.OBAtom.IsHbondAcceptor(), all_atoms):
if atom.atomicnum not in [9, 17, 35, 53] and atom.idx not in self.altconf: # Exclude halogen atoms
a_orig_idx = self.Mapper.mapid(atom.idx, mtype=self.mtype, bsid=self.bsid)
a_orig_atom = self.Mapper.id_to_atom(a_orig_idx)
@@ -978,6 +979,7 @@ class Ligand(Mol):
self.complex = cclass
self.molecule = ligand.mol # Pybel Molecule
self.smiles = self.molecule.write(format='can') # SMILES String
+ self.inchikey = self.molecule.write(format='inchikey')
self.can_to_pdb = ligand.can_to_pdb
if not len(self.smiles) == 0:
self.smiles = self.smiles.split()[0]
@@ -1256,7 +1258,7 @@ class PDBComplex:
self.sourcefiles = {}
self.information = {}
self.corrected_pdb = ''
- self.output_path = '/tmp'
+ self._output_path = '/tmp'
self.pymol_name = None
self.modres = set()
self.resis = []
@@ -1284,7 +1286,7 @@ class PDBComplex:
pdbparser = PDBParser(pdbpath, as_string=as_string) # Parse PDB file to find errors and get additonal data
# #@todo Refactor and rename here
self.Mapper.proteinmap = pdbparser.proteinmap
- self.Mapper.reversed_proteinmap = inv_map = {v: k for k, v in self.Mapper.proteinmap.iteritems()}
+ self.Mapper.reversed_proteinmap = inv_map = {v: k for k, v in self.Mapper.proteinmap.items()}
self.modres = pdbparser.modres
self.covalent = pdbparser.covalent
self.altconf = pdbparser.altconformations
@@ -1294,20 +1296,23 @@ class PDBComplex:
if pdbparser.num_fixed_lines > 0:
write_message('%i lines automatically fixed in PDB input file.\n' % pdbparser.num_fixed_lines)
# Save modified PDB file
- basename = os.path.basename(pdbpath).split('.')[0]
+ if not as_string:
+ basename = os.path.basename(pdbpath).split('.')[0]
+ else:
+ basename = "from_stdin"
pdbpath_fixed = tmpfile(prefix='plipfixed.' + basename + '_', direc=self.output_path)
create_folder_if_not_exists(self.output_path)
self.sourcefiles['pdbcomplex'] = pdbpath_fixed
self.corrected_pdb = re.sub(r'[^\x00-\x7F]+', ' ', self.corrected_pdb) # Strip non-unicode chars
- with open(pdbpath_fixed, 'w') as f:
- f.write(self.corrected_pdb)
+ if not config.NOFIXFILE: # Only write to file if this option is not activated
+ with open(pdbpath_fixed, 'w') as f:
+ f.write(self.corrected_pdb)
self.information['pdbfixes'] = True
- if as_string:
- self.protcomplex, self.filetype = read_pdb(self.sourcefiles['pdbstring'], as_string=as_string)
- else:
+
+ if not as_string:
self.sourcefiles['filename'] = os.path.basename(self.sourcefiles['pdbcomplex'])
- self.protcomplex, self.filetype = read_pdb(self.sourcefiles['pdbcomplex'], as_string=as_string)
+ self.protcomplex, self.filetype = read_pdb(self.corrected_pdb, as_string=True)
# Update the model in the Mapper class instance
self.Mapper.original_structure = self.protcomplex.OBMol
@@ -1434,8 +1439,8 @@ class PDBComplex:
@property
def output_path(self):
- return self.output_path
+ return self._output_path
@output_path.setter
def output_path(self, path):
- self.output_path = tilde_expansion(path)
+ self._output_path = tilde_expansion(path)
=====================================
plip/modules/pymolplip.py
=====================================
--- a/plip/modules/pymolplip.py
+++ b/plip/modules/pymolplip.py
@@ -69,7 +69,7 @@ class PyMOLVisualizer:
idlist = list(set(idlist)) # Remove duplicates
if not selection_exists:
cmd.select(selname, 'None') # Empty selection first
- idchunks = [idlist[i:i+chunksize] for i in xrange(0, len(idlist), chunksize)]
+ idchunks = [idlist[i:i+chunksize] for i in range(0, len(idlist), chunksize)]
for idchunk in idchunks:
cmd.select(selname, '%s or (id %s)' % (selname, '+'.join(map(str, idchunk))))
if restrict is not None:
=====================================
plip/modules/report.py
=====================================
--- a/plip/modules/report.py
+++ b/plip/modules/report.py
@@ -3,18 +3,23 @@ Protein-Ligand Interaction Profiler - Analyze and visualize protein-ligand inter
report.py - Write PLIP results to output files.
"""
+# Compatibility
+from __future__ import print_function
+from __future__ import absolute_import
# Python Standard Library
import time
from operator import itemgetter
import sys
-import config
+
+# Own modules
+from . import config
# External libraries
import lxml.etree as et
-__version__ = '1.3.4'
+__version__ = '1.4.0'
class StructureReport:
"""Creates reports (xml or txt) for one structure/"""
@@ -50,7 +55,7 @@ class StructureReport:
pdbfixes = et.SubElement(report, 'pdbfixes')
pdbfixes.text = str(self.mol.information['pdbfixes'])
filename = et.SubElement(report, 'filename')
- filename.text = str(self.mol.sourcefiles['filename'])
+ filename.text = str(self.mol.sourcefiles.get('filename') or None)
exligs = et.SubElement(report, 'excluded_ligands')
for i, exlig in enumerate(self.excluded):
e = et.SubElement(exligs, 'excluded_ligand', id=str(i + 1))
@@ -92,7 +97,10 @@ class StructureReport:
if not as_string:
et.ElementTree(self.xmlreport).write('%s/report.xml' % self.outpath, pretty_print=True, xml_declaration=True)
else:
- print et.tostring(self.xmlreport, pretty_print=True)
+ output = et.tostring(self.xmlreport, pretty_print=True)
+ if config.RAWSTRING:
+ output = repr(output)
+ print(output)
def write_txt(self, as_string=False):
"""Write the TXT report"""
@@ -100,7 +108,10 @@ class StructureReport:
with open('%s/report.txt' % self.outpath, 'w') as f:
[f.write(textline + '\n') for textline in self.txtreport]
else:
- print '\n'.join(self.txtreport)
+ output = '\n'.join(self.txtreport)
+ if config.RAWSTRING:
+ output = repr(output)
+ print(output)
class BindingSiteReport:
@@ -350,6 +361,7 @@ class BindingSiteReport:
composite = et.SubElement(identifiers, 'composite')
members = et.SubElement(identifiers, 'members')
smiles = et.SubElement(identifiers, 'smiles')
+ inchikey = et.SubElement(identifiers, 'inchikey')
# Ligand properties. Number of (unpaired) functional atoms and rings.
lig_properties = et.SubElement(report, 'lig_properties')
@@ -391,6 +403,7 @@ class BindingSiteReport:
longname.text = self.longname
ligtype.text = self.ligtype
smiles.text = self.ligand.smiles
+ inchikey.text = self.ligand.inchikey
num_heavy_atoms.text = str(self.ligand.heavy_atoms) # Number of heavy atoms in ligand
for i, member in enumerate(self.lig_members):
bsid = ":".join(str(element) for element in member)
=====================================
plip/modules/supplemental.py
=====================================
--- a/plip/modules/supplemental.py
+++ b/plip/modules/supplemental.py
@@ -8,7 +8,7 @@ from __future__ import print_function
from __future__ import absolute_import
# PLIP Modules
-import plip.modules.config as config
+from . import config
# Python standard library
import re
@@ -92,7 +92,7 @@ def vector(p1, p2):
:param p2: coordinates of point p2
:returns : numpy array with vector coordinates
"""
- return None if len(p1) != len(p2) else np.array([p2[i] - p1[i] for i in xrange(len(p1))])
+ return None if len(p1) != len(p2) else np.array([p2[i] - p1[i] for i in range(len(p1))])
def vecangle(v1, v2, deg=True):
@@ -123,7 +123,7 @@ def centroid(coo):
:param coo: Array of coordinate arrays
:returns : centroid coordinates as list
"""
- return map(np.mean, (([c[0] for c in coo]), ([c[1] for c in coo]), ([c[2] for c in coo])))
+ return list(map(np.mean, (([c[0] for c in coo]), ([c[1] for c in coo]), ([c[2] for c in coo]))))
def projection(pnormal1, ppoint, tpoint):
@@ -334,15 +334,16 @@ def get_isomorphisms(reference, lig):
return isomorphs
-def canonicalize(lig):
+def canonicalize(lig, preserve_bond_order=False):
"""Get the canonical atom order for the ligand."""
atomorder = None
# Get canonical atom order
lig = pybel.ob.OBMol(lig.OBMol)
- for bond in pybel.ob.OBMolBondIter(lig):
- if bond.GetBondOrder() != 1:
- bond.SetBondOrder(1)
+ if not preserve_bond_order:
+ for bond in pybel.ob.OBMolBondIter(lig):
+ if bond.GetBondOrder() != 1:
+ bond.SetBondOrder(1)
lig.DeleteData(pybel.ob.StereoData)
lig = pybel.Molecule(lig)
testcan = lig.write(format='can')
@@ -398,33 +399,40 @@ def read(fil):
zf = zipfile.ZipFile(fil, 'r')
return zf.open(zf.infolist()[0].filename)
else:
- try:
- codecs.open(fil, 'r', 'utf-8').read()
- return codecs.open(fil, 'r', 'utf-8')
- except UnicodeDecodeError:
- return open(fil, 'r')
+ return open(fil, 'r')
+ #try:
+ # codecs.open(fil, 'r', 'utf-8').read()
+ # return codecs.open(fil, 'r', 'utf-8')
+ #except UnicodeDecodeError:
+ # return open(fil, 'r')
def readmol(path, as_string=False):
"""Reads the given molecule file and returns the corresponding Pybel molecule as well as the input file type.
In contrast to the standard Pybel implementation, the file is closed properly."""
supported_formats = ['pdb', 'mmcif']
- obc = pybel.ob.OBConversion()
+ # Fix for Windows-generated files: Remove carriage return characters
+ if "\r" in path and as_string:
+ path = path.replace('\r', '')
for sformat in supported_formats:
+ obc = pybel.ob.OBConversion()
obc.SetInFormat(sformat)
write_message("Detected {} as format. Now trying to read file with OpenBabel...\n".format(sformat), mtype='debug')
mol = pybel.ob.OBMol()
# Read molecules with single bond information
if as_string:
- read_file = pybel.readstring(format=sformat, filename=path, opt={"s": None})
+ try:
+ mymol = pybel.readstring(sformat, path)
+ except IOError:
+ sysexit(4, 'No valid file format provided.')
else:
read_file = pybel.readfile(format=sformat, filename=path, opt={"s": None})
- try:
- mymol = read_file.next()
- except StopIteration:
- sysexit(4, 'File contains no valid molecules.\n')
+ try:
+ mymol = next(read_file)
+ except StopIteration:
+ sysexit(4, 'File contains no valid molecules.\n')
write_message("Molecule successfully read.\n", mtype='debug')
=====================================
plip/modules/visualize.py
=====================================
--- a/plip/modules/visualize.py
+++ b/plip/modules/visualize.py
@@ -7,10 +7,10 @@ visualize.py - Visualization of PLIP results using PyMOL.
from __future__ import absolute_import
# Own modules
-from plip.modules.supplemental import initialize_pymol, start_pymol, write_message, colorlog, sysexit
-import plip.modules.config as config
-from plip.modules.pymolplip import PyMOLVisualizer
-from plip.modules.plipremote import VisualizerData
+from .supplemental import initialize_pymol, start_pymol, write_message, colorlog, sysexit
+from . import config
+from .pymolplip import PyMOLVisualizer
+from .plipremote import VisualizerData
# Python Standard Library
import json
@@ -29,7 +29,7 @@ def select_by_ids(selname, idlist, selection_exists=False, chunksize=20, restric
idlist = list(set(idlist)) # Remove duplicates
if not selection_exists:
cmd.select(selname, 'None') # Empty selection first
- idchunks = [idlist[i:i+chunksize] for i in xrange(0, len(idlist), chunksize)]
+ idchunks = [idlist[i:i+chunksize] for i in range(0, len(idlist), chunksize)]
for idchunk in idchunks:
cmd.select(selname, '%s or (id %s)' % (selname, '+'.join(map(str, idchunk))))
if restrict is not None:
=====================================
plip/modules/webservices.py
=====================================
--- a/plip/modules/webservices.py
+++ b/plip/modules/webservices.py
@@ -5,10 +5,15 @@ webservices.py - Connect to various webservices to retrieve data
# Python standard library
from __future__ import absolute_import
-import urllib2
+
+try: # Python 3
+ from urllib.request import urlopen
+ from urllib.error import HTTPError
+except ImportError: # Fallback Python 2.x
+ from urllib2 import urlopen, HTTPError
# Own modules
-from plip.modules.supplemental import write_message, sysexit
+from .supplemental import write_message, sysexit
# External libraries
import lxml.etree as et
@@ -18,7 +23,7 @@ import lxml.etree as et
def check_pdb_status(pdbid):
"""Returns the status and up-to-date entry in the PDB for a given PDB ID"""
url = 'http://www.rcsb.org/pdb/rest/idStatus?structureId=%s' % pdbid
- xmlf = urllib2.urlopen(url)
+ xmlf = urlopen(url)
xml = et.parse(xmlf)
xmlf.close()
status = None
@@ -45,11 +50,11 @@ def fetch_pdb(pdbid):
write_message('Downloading file from PDB ... ')
pdburl = 'http://www.rcsb.org/pdb/files/%s.pdb' % current_entry # Get URL for current entry
try:
- pdbfile = urllib2.urlopen(pdburl).read()
+ pdbfile = urlopen(pdburl).read().decode()
# If no PDB file is available, a text is now shown with "We're sorry, but ..."
# Could previously be distinguished by an HTTP error
if 'sorry' in pdbfile:
sysexit(5, "No file in PDB format available from wwPDB for the given PDB ID.\n")
- except urllib2.HTTPError:
+ except HTTPError:
sysexit(5, "No file in PDB format available from wwPDB for the given PDB ID.\n")
return [pdbfile, current_entry]
=====================================
plip/plipcmd
=====================================
--- a/plip/plipcmd
+++ b/plip/plipcmd
@@ -9,13 +9,13 @@ from __future__ import print_function
from __future__ import absolute_import
# Own modules
-from plip.modules.preparation import *
-from plip.modules.visualize import visualize_in_pymol
-from plip.modules.plipremote import VisualizerData
-from plip.modules.report import StructureReport,__version__
-from plip.modules import config
-from plip.modules.mp import parallel_fn
-from plip.modules.webservices import check_pdb_status, fetch_pdb
+from modules.preparation import *
+from modules.visualize import visualize_in_pymol
+from modules.plipremote import VisualizerData
+from modules.report import StructureReport,__version__
+from modules import config
+from modules.mp import parallel_fn
+from modules.webservices import check_pdb_status, fetch_pdb
# Python standard library
import sys
@@ -24,6 +24,7 @@ from argparse import ArgumentParser
import time
import multiprocessing
import json
+
# External libraries
import lxml.etree as et
@@ -44,14 +45,17 @@ def threshold_limiter(aparser, arg):
-def process_pdb(pdbfile, outpath):
+def process_pdb(pdbfile, outpath, as_string=False):
"""Analysis of a single PDB file. Can generate textual reports XML, PyMOL session files and images as output."""
- startmessage = '\nStarting analysis of %s\n' % pdbfile.split('/')[-1]
+ if not as_string:
+ startmessage = '\nStarting analysis of %s\n' % pdbfile.split('/')[-1]
+ else:
+ startmessage = "Starting analysis from stdin.\n"
write_message(startmessage)
write_message('='*len(startmessage)+'\n')
mol = PDBComplex()
mol.output_path = outpath
- mol.load_pdb(pdbfile)
+ mol.load_pdb(pdbfile, as_string=as_string)
# #@todo Offers possibility for filter function from command line (by ligand chain, position, hetid)
for ligand in mol.ligands:
mol.characterize_complex(ligand)
@@ -79,10 +83,10 @@ def process_pdb(pdbfile, outpath):
[visualize_in_pymol(plcomplex) for plcomplex in complexes]
if config.XML: # Generate report in xml format
- streport.write_xml()
+ streport.write_xml(as_string=config.STDOUT)
if config.TXT: # Generate report in txt (rst) format
- streport.write_txt()
+ streport.write_txt(as_string=config.STDOUT)
def download_structure(inputpdbid):
"""Given a PDB ID, downloads the corresponding PDB structure.
@@ -127,13 +131,23 @@ def main(inputstructs, inputpdbids):
if inputstructs is not None: # Process PDB file(s)
num_structures = len(inputstructs)
inputstructs = remove_duplicates(inputstructs)
+ read_from_stdin = False
for inputstruct in inputstructs:
- if os.path.getsize(inputstruct) == 0:
- sysexit(2, 'Empty PDB file\n') # Exit if input file is empty
- if num_structures > 1:
- basename = inputstruct.split('.')[-2].split('/')[-1]
- config.OUTPATH = '/'.join([config.BASEPATH, basename])
- process_pdb(inputstruct, config.OUTPATH)
+ if inputstruct == '-':
+ inputstruct = sys.stdin.read()
+ read_from_stdin = True
+ if config.RAWSTRING:
+ if sys.version_info < (3,):
+ inputstruct = bytes(inputstruct).decode('unicode_escape')
+ else:
+ inputstruct = bytes(inputstruct, 'utf8').decode('unicode_escape')
+ else:
+ if os.path.getsize(inputstruct) == 0:
+ sysexit(2, 'Empty PDB file\n') # Exit if input file is empty
+ if num_structures > 1:
+ basename = inputstruct.split('.')[-2].split('/')[-1]
+ config.OUTPATH = '/'.join([config.BASEPATH, basename])
+ process_pdb(inputstruct, config.OUTPATH, as_string=read_from_stdin)
else: # Try to fetch the current PDB structure(s) directly from the RCBS server
num_pdbids = len(inputpdbids)
inputpdbids =remove_duplicates(inputpdbids)
@@ -157,9 +171,12 @@ if __name__ == '__main__':
parser = ArgumentParser(prog="PLIP", description=descript)
pdbstructure = parser.add_mutually_exclusive_group(required=True) # Needs either PDB ID or file
- pdbstructure.add_argument("-f", "--file", dest="input", nargs="+")
+ pdbstructure.add_argument("-f", "--file", dest="input", nargs="+", help="Set input file, '-' reads from stdin") # '-' as file name reads from stdin
pdbstructure.add_argument("-i", "--input", dest="pdbid", nargs="+")
- parser.add_argument("-o", "--out", dest="outpath", default="./")
+ outputgroup = parser.add_mutually_exclusive_group(required=False) # Needs either outpath or stdout
+ outputgroup.add_argument("-o", "--out", dest="outpath", default="./")
+ outputgroup.add_argument("-O", "--stdout", dest="stdout", action="store_true", default=False, help="Write to stdout instead of file")
+ parser.add_argument("--rawstring", dest="use_raw_string", default=False, action="store_true", help="Use Python raw strings for stdout and stdin")
parser.add_argument("-v", "--verbose", dest="verbose", default=False, help="Set verbose mode", action="store_true")
parser.add_argument("-p", "--pics", dest="pics", default=False, help="Additional pictures", action="store_true")
parser.add_argument("-x", "--xml", dest="xml", default=False, help="Generate report file in XML format",
@@ -173,8 +190,7 @@ if __name__ == '__main__':
"If not set, PLIP uses all available CPUs if possible.",
type=int)
parser.add_argument("--breakcomposite", dest="breakcomposite", default=False,
- help="Don't combine ligand fragments into with covalent bonds but treat them as single ligands"
- "fot the analysis.",
+ help="Don't combine ligand fragments with covalent bonds but treat them as single ligands for the analysis.",
action="store_true")
parser.add_argument("--altlocation", dest="altlocation", default=False,
help="Also consider alternate locations for atoms (e.g. alternate conformations).",
@@ -185,6 +201,9 @@ if __name__ == '__main__':
parser.add_argument("--nofix", dest="nofix", default=False,
help="Turns off fixing of PDB files.",
action="store_true")
+ parser.add_argument("--nofixfile", dest="nofixfile", default=False,
+ help="Turns off writing files for fixed PDB files.",
+ action="store_true")
parser.add_argument("--dnareceptor", dest="dnareceptor", default=False,
help="Uses the DNA instead of the protein as a receptor for interactions.",
action="store_true")
@@ -220,6 +239,8 @@ if __name__ == '__main__':
config.TXT = arguments.txt
config.PICS = arguments.pics
config.PYMOL = arguments.pymol
+ config.STDOUT = arguments.stdout
+ config.RAWSTRING = arguments.use_raw_string
config.OUTPATH = arguments.outpath
config.OUTPATH = tilde_expansion("".join([config.OUTPATH, '/'])
if not config.OUTPATH.endswith('/') else config.OUTPATH)
@@ -229,6 +250,7 @@ if __name__ == '__main__':
config.PEPTIDES = arguments.peptides
config.INTRA = arguments.intra
config.NOFIX = arguments.nofix
+ config.NOFIXFILE = arguments.nofixfile
config.KEEPMOD = arguments.keepmod
config.DNARECEPTOR = arguments.dnareceptor
# Assign values to global thresholds
=====================================
plip/test/test_basic_functions.py
=====================================
--- a/plip/test/test_basic_functions.py
+++ b/plip/test/test_basic_functions.py
@@ -77,7 +77,7 @@ class GeometryTest(unittest.TestCase):
"""Generate random data for the tests"""
# Generate two random n-dimensional float vectors, with -100 <= n <= 100 and values 0 <= i <= 1
dim = random.randint(1, 100)
- self.rnd_vec = [random.uniform(-100, 100) for i in xrange(dim)]
+ self.rnd_vec = [random.uniform(-100, 100) for i in range(dim)]
def test_euclidean(self):
"""Tests for mathematics.euclidean"""
=====================================
setup.py
=====================================
--- a/setup.py
+++ b/setup.py
@@ -6,7 +6,7 @@ setup.py - Setup configuration file for pip, etc.
from setuptools import setup
setup(name='plip',
- version='1.3.5',
+ version='1.4.0',
description='PLIP - Fully automated protein-ligand interaction profiler',
classifiers=[
'Development Status :: 5 - Production/Stable',
@@ -14,17 +14,19 @@ setup(name='plip',
'Natural Language :: English',
'License :: OSI Approved :: GNU General Public License v2 (GPLv2)',
'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3.5',
'Topic :: Scientific/Engineering :: Bio-Informatics'
],
url='https://github.com/ssalentin/plip',
author='Sebastian Salentin',
- author_email='sebastian.salentin at biotec.tu-dresden.de',
+ author_email='sebastian.salentin at tu-dresden.de',
license='GPLv2',
packages=['plip', 'plip/modules'],
scripts=['plip/plipcmd'],
install_requires=[
'openbabel',
'numpy',
- 'lxml'
+ 'lxml',
+ 'future'
],
zip_safe=False)
View it on GitLab: https://salsa.debian.org/med-team/plip/compare/b11eaf33a9f454275b0398b2e302ae723bb50511...caf52b101f6144ff869e4eb9b0eb6349578bf44b
---
View it on GitLab: https://salsa.debian.org/med-team/plip/compare/b11eaf33a9f454275b0398b2e302ae723bb50511...caf52b101f6144ff869e4eb9b0eb6349578bf44b
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.alioth.debian.org/pipermail/debian-med-commit/attachments/20180412/c9ee6cfa/attachment-0001.html>
More information about the debian-med-commit
mailing list