Remove some unused code

- Remove all code which was previously marked with
  `NotImplementedError("unused")`.
- Remove unsued command line arguments
This commit is contained in:
Thomas Holder
2023-12-21 22:24:29 +01:00
parent 6ee0df8e6d
commit 9ea6d8815d
9 changed files with 17 additions and 370 deletions

View File

@@ -2,6 +2,17 @@
Changelog Changelog
********* *********
Upcoming release (TBD)
======================
Changes
-------
* Removed the following unused command line options: ``-t``, ``--thermophile``,
``-a``, ``--alignment``, ``-m``, ``--mutation``, ``--mutator``,
``--mutator-option``
* Removed several unused API functions
Current Current
======= =======

View File

@@ -10,9 +10,9 @@ PROPKA predicts the pKa values of ionizable groups in proteins and
protein-ligand complexes based in the 3D structure. The protein-ligand complexes based in the 3D structure. The
:program:`propka3` command has the following options:: :program:`propka3` command has the following options::
propka3 [-h] [-f FILENAMES] [-r REFERENCE] [-c CHAINS] [-i TITRATE_ONLY] [-t THERMOPHILES] [-a ALIGNMENT] [-m MUTATIONS] propka3 [-h] [-f FILENAMES] [-r REFERENCE] [-c CHAINS] [-i TITRATE_ONLY]
[-v VERSION_LABEL] [-p PARAMETERS] [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-o PH] [-w WINDOW WINDOW WINDOW] [-v VERSION_LABEL] [-p PARAMETERS] [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-o PH] [-w WINDOW WINDOW WINDOW]
[-g GRID GRID GRID] [--mutator MUTATOR] [--mutator-option MUTATOR_OPTIONS] [-d] [-l] [-k] [-q] [--protonate-all] [-g GRID GRID GRID] [-d] [-l] [-k] [-q] [--protonate-all]
input_pdb input_pdb
@@ -47,21 +47,6 @@ protein-ligand complexes based in the 3D structure. The
should be a comma-separated list of "chain:resnum" should be a comma-separated list of "chain:resnum"
values; for example: ``-i "A:10,A:11"`` (default: None) values; for example: ``-i "A:10,A:11"`` (default: None)
.. option:: -t THERMOPHILES, --thermophile THERMOPHILES
defining a thermophile filename; usually used in
'alignment-mutations' (default: None)
.. option:: -a ALIGNMENT, --alignment ALIGNMENT
alignment file connecting <filename> and <thermophile>
[<thermophile>.pir] (default: None)
.. option:: -m MUTATIONS, --mutation MUTATIONS
specifying mutation labels which is used to modify
<filename> according to, e.g. N25R/N181D (default: None)
.. option:: --version .. option:: --version
show program's version number and exit show program's version number and exit
@@ -90,16 +75,6 @@ protein-ligand complexes based in the 3D structure. The
setting the pH-grid to calculate e.g. stability related setting the pH-grid to calculate e.g. stability related
properties (default: (0.0, 14.0, 0.1)) properties (default: (0.0, 14.0, 0.1))
.. option:: --mutator MUTATOR
setting approach for mutating <filename>
[alignment/scwrl/jackal] (default: None)
.. option:: --mutator-option MUTATOR_OPTIONS
setting property for mutator [e.g. type="side-chain"]
(default: None)
.. option:: -d, --display-coupled-residues .. option:: -d, --display-coupled-residues
Displays alternative pKa values due to coupling of Displays alternative pKa values due to coupling of

View File

@@ -7,8 +7,7 @@ The :class:`Atom` class contains all atom information found in the PDB file.
""" """
import string import string
from typing import cast, List, NoReturn, Optional, TYPE_CHECKING from typing import List, Optional, TYPE_CHECKING
import warnings
from propka.lib import make_tidy_atom_label from propka.lib import make_tidy_atom_label
from . import hybrid36 from . import hybrid36
@@ -46,7 +45,6 @@ class Atom:
group: Optional["Group"] = None group: Optional["Group"] = None
group_type: Optional[str] = None group_type: Optional[str] = None
cysteine_bridge: bool = False cysteine_bridge: bool = False
residue: NoReturn = None # type: ignore[assignment]
conformation_container: Optional["ConformationContainer"] = None conformation_container: Optional["ConformationContainer"] = None
molecular_container: Optional["MolecularContainer"] = None molecular_container: Optional["MolecularContainer"] = None
is_protonated: bool = False is_protonated: bool = False
@@ -87,7 +85,6 @@ class Atom:
Args: Args:
line: Line from a PDB file to set properties of atom. line: Line from a PDB file to set properties of atom.
""" """
self.number_of_bonded_elements: NoReturn = cast(NoReturn, {}) # FIXME unused?
self.bonded_atoms: List[Atom] = [] self.bonded_atoms: List[Atom] = []
self.set_properties(line) self.set_properties(line)
fmt = "{r.name:3s}{r.res_num:>4d}{r.chain_id:>2s}" fmt = "{r.name:3s}{r.res_num:>4d}{r.chain_id:>2s}"
@@ -302,45 +299,6 @@ class Atom:
atom_label=make_tidy_atom_label(self.name, self.element)) atom_label=make_tidy_atom_label(self.name, self.element))
return str_ return str_
def make_pdb_line2(self, numb=None, name=None, res_name=None, chain_id=None,
res_num=None, x=None, y=None, z=None, occ=None,
beta=None):
"""Create a PDB line.
TODO - this could/should be a @property method/attribute
TODO - figure out difference between make_pdb_line, and make_pdb_line2
Returns:
String with PDB line.
"""
warnings.warn("only used by unused function")
if numb is None:
numb = self.numb
if name is None:
name = self.name
if res_name is None:
res_name = self.res_name
if chain_id is None:
chain_id = self.chain_id
if res_num is None:
res_num = self.res_num
if x is None:
x = self.x
if y is None:
y = self.y
if z is None:
z = self.z
if occ is None:
occ = self.occ
if beta is None:
beta = self.beta
str_ = PDB_LINE_FMT2.format(
numb=numb, res_name=res_name, chain_id=chain_id, res_num=res_num,
x=x, y=y, z=z, occ=occ, beta=beta,
atom_label=make_tidy_atom_label(name, self.element)
)
return str_
def get_tidy_label(self): def get_tidy_label(self):
"""Returns a 'tidier' atom label for printing the new pdbfile """Returns a 'tidier' atom label for printing the new pdbfile
@@ -353,13 +311,3 @@ class Atom:
def __str__(self): def __str__(self):
"""Return an undefined-format string version of this atom.""" """Return an undefined-format string version of this atom."""
return STR_FMT.format(r=self) return STR_FMT.format(r=self)
def set_residue(self, residue: NoReturn):
""" Makes a reference to the parent residue
Args:
residue: the parent residue
"""
raise NotImplementedError("unused")
if self.residue is None:
self.residue = residue

View File

@@ -87,63 +87,6 @@ class BondMaker:
self.backbone_atoms = list(self.intra_residue_backbone_bonds.keys()) self.backbone_atoms = list(self.intra_residue_backbone_bonds.keys())
self.terminal_oxygen_names = ['OXT', 'O\'\''] self.terminal_oxygen_names = ['OXT', 'O\'\'']
def find_bonds_for_protein(self, protein):
"""Bonds proteins based on the way atoms normally bond.
Args:
protein: the protein to search for bonds
"""
raise NotImplementedError("unused")
_LOGGER.info('++++ Side chains ++++')
# side chains
for chain in protein.chains:
for residue in chain.residues:
if residue.res_name.replace(' ', '') not in ['N+', 'C-']:
self.find_bonds_for_side_chain(residue.atoms)
_LOGGER.info('++++ Backbones ++++')
# backbone
last_residues = []
for chain in protein.chains:
for i in range(1, len(chain.residues)):
if (chain.residues[i-1].res_name.replace(' ', '')
not in ['N+', 'C-']):
if (chain.residues[i].res_name.replace(' ', '')
not in ['N+', 'C-']):
self.connect_backbone(chain.residues[i-1],
chain.residues[i])
last_residues.append(chain.residues[i])
_LOGGER.info('++++ terminal oxygen ++++')
# terminal OXT
for last_residue in last_residues:
self.find_bonds_for_terminal_oxygen(last_residue)
_LOGGER.info('++++ cysteines ++++')
# Cysteines
for chain in protein.chains:
for i in range(0, len(chain.residues)):
if chain.residues[i].res_name == 'CYS':
for j in range(0, len(chain.residues)):
if chain.residues[j].res_name == 'CYS' and j != i:
self.check_for_cysteine_bonds(chain.residues[i],
chain.residues[j])
def check_for_cysteine_bonds(self, cys1, cys2):
"""Looks for potential bonds between two cysteines.
Args:
cys1: one of the cysteines to check
cys1: one of the cysteines to check
"""
raise NotImplementedError("unused")
for atom1 in cys1.atoms:
if atom1.name == 'SG':
for atom2 in cys2.atoms:
if atom2.name == 'SG':
dist = propka.calculations.squared_distance(atom1,
atom2)
# TODO - is SS_dist_squared an attribute of this class?
if dist < self.SS_dist_squared:
self.make_bond(atom1, atom2)
def find_bonds_for_terminal_oxygen(self, residue): def find_bonds_for_terminal_oxygen(self, residue):
"""Look for bonds for terminal oxygen. """Look for bonds for terminal oxygen.
@@ -423,34 +366,3 @@ class BondMaker:
atom2.bonded_atoms.append(atom1) atom2.bonded_atoms.append(atom1)
if atom2 not in atom1.bonded_atoms: if atom2 not in atom1.bonded_atoms:
atom1.bonded_atoms.append(atom2) atom1.bonded_atoms.append(atom2)
def generate_protein_bond_dictionary(self, atoms):
"""Generate dictionary of protein bonds.
Args:
atoms: list of atoms for bonding
"""
for atom in atoms:
for bonded_atom in atom.bonded_atoms:
resi_i = atom.res_name
name_i = atom.name
resi_j = bonded_atom.res_name
name_j = bonded_atom.name
if name_i not in (
self.backbone_atoms
or name_j not in self.backbone_atoms):
if name_i not in (
self.terminal_oxygen_names
and name_j not in self.terminal_oxygen_names):
if resi_i not in list(self.protein_bonds.keys()):
self.protein_bonds[resi_i] = {}
if name_i not in self.protein_bonds[resi_i]:
self.protein_bonds[resi_i][name_i] = []
if name_j not in self.protein_bonds[resi_i][name_i]:
self.protein_bonds[resi_i][name_i].append(name_j)
if resi_j not in list(self.protein_bonds.keys()):
self.protein_bonds[resi_j] = {}
if name_j not in self.protein_bonds[resi_j]:
self.protein_bonds[resi_j][name_j] = []
if name_i not in self.protein_bonds[resi_j][name_j]:
self.protein_bonds[resi_j][name_j].append(name_i)

View File

@@ -6,7 +6,7 @@ Container data structure for molecular conformations.
""" """
import logging import logging
import functools import functools
from typing import Callable, Dict, Iterable, Iterator, List, NoReturn, Optional, TYPE_CHECKING, Set from typing import Callable, Dict, Iterable, Iterator, List, Optional, TYPE_CHECKING, Set
from propka.lib import Options from propka.lib import Options
from propka.version import Version from propka.version import Version
@@ -497,18 +497,6 @@ class ConformationContainer:
group for group in self.groups group for group in self.groups
if group.residue_type in self.parameters.ions.keys()] if group.residue_type in self.parameters.ions.keys()]
def get_group_names(self, group_list: NoReturn) -> NoReturn: # FIXME unused?
"""Get names of groups in list.
Args:
group_list: list to check
Returns:
list of groups
"""
if TYPE_CHECKING:
assert False
return [group for group in self.groups if group.type in group_list]
def get_ligand_atoms(self) -> List["Atom"]: def get_ligand_atoms(self) -> List["Atom"]:
"""Get atoms associated with ligands. """Get atoms associated with ligands.

View File

@@ -11,7 +11,7 @@ Routines and classes for storing groups important to PROPKA calculations.
""" """
import logging import logging
import math import math
from typing import cast, Dict, Iterable, List, NoReturn, Optional from typing import Dict, List, Optional
import propka.ligand import propka.ligand
from propka.parameters import Parameters from propka.parameters import Parameters
@@ -119,8 +119,6 @@ class Group:
fmt = "{type:<3s}{name:>4s}{chain:>2s}" fmt = "{type:<3s}{name:>4s}{chain:>2s}"
self.label = fmt.format( self.label = fmt.format(
type=self.residue_type, name=atom.name, chain=atom.chain_id) type=self.residue_type, name=atom.name, chain=atom.chain_id)
# container for squared distances
self.squared_distances: NoReturn = cast(NoReturn, {}) # FIXME unused?
def couple_covalently(self, other: "Group") -> None: def couple_covalently(self, other: "Group") -> None:
"""Couple this group with another group. """Couple this group with another group.
@@ -162,46 +160,6 @@ class Group:
""" """
return self.non_covalently_coupled_groups return self.non_covalently_coupled_groups
def share_determinants(self, others: Iterable["Group"]) -> None:
"""Share determinants between this group and others.
Args:
others: list of other groups
"""
raise NotImplementedError("unused")
# for each determinant type
for other in others:
if other == self:
the_other = other
continue
for type_ in ['sidechain', 'backbone', 'coulomb']:
for det in other.determinants[type_]:
self.share_determinant(det, type_)
# recalculate pka values
self.calculate_total_pka()
the_other.calculate_total_pka()
def share_determinant(self, new_determinant: Determinant, type_: str) -> None:
"""Add determinant to this group's list of determinants.
Args:
new_determinant: determinant to add
type_: type of determinant
"""
added = False
# first check if we already have a determinant with this label
for own_determinant in self.determinants[type_]:
if own_determinant.group == new_determinant.group:
# if so, find the average value
avr = 0.5*(own_determinant.value + new_determinant.value)
own_determinant.value = avr
new_determinant.value = avr
added = True
# otherwise we just add the determinant to our list
if not added:
self.determinants[type_].append(
Determinant(new_determinant.group, new_determinant.value))
def __eq__(self, other): def __eq__(self, other):
"""Needed for creating sets of groups.""" """Needed for creating sets of groups."""
if self.atom.type == 'atom': if self.atom.type == 'atom':

View File

@@ -30,7 +30,6 @@ EXPECTED_ATOM_NUMBERS = {'ALA': 5, 'ARG': 11, 'ASN': 8, 'ASP': 8, 'CYS': 6,
class Options: class Options:
# Note: All the "NoReturn" members appear to be unused # Note: All the "NoReturn" members appear to be unused
alignment: NoReturn # Optional[List[str]]
chains: Optional[List[str]] chains: Optional[List[str]]
display_coupled_residues: bool = False display_coupled_residues: bool = False
filenames: List[str] # List[Path]? filenames: List[str] # List[Path]?
@@ -38,15 +37,11 @@ class Options:
input_pdb: str # Path? input_pdb: str # Path?
keep_protons: bool = False keep_protons: bool = False
log_level: str = 'INFO' log_level: str = 'INFO'
mutations: NoReturn # Optional[List[str]]
mutator: NoReturn # Optional[str] # alignment/scwrl/jackal
mutator_options: NoReturn # Optional[List[str]]
pH: NoReturn # float = 7.0 pH: NoReturn # float = 7.0
parameters: Path parameters: Path
protonate_all: bool = False protonate_all: bool = False
reference: NoReturn # str = 'neutral' reference: NoReturn # str = 'neutral'
reuse_ligand_mol2_file: bool = False # only used by unused function reuse_ligand_mol2_file: bool = False # only used by unused function
thermophiles: NoReturn # Optional[List[str]]
titrate_only: Optional[List[_T_RESIDUE_TUPLE]] titrate_only: Optional[List[_T_RESIDUE_TUPLE]]
window: Tuple[float, float, float] = (0.0, 14.0, 1.0) window: Tuple[float, float, float] = (0.0, 14.0, 1.0)
@@ -272,18 +267,6 @@ def build_parser(parser=None):
help=('Treat only the specified residues as titratable. Value should ' help=('Treat only the specified residues as titratable. Value should '
'be a comma-separated list of "chain:resnum" values; for ' 'be a comma-separated list of "chain:resnum" values; for '
'example: -i "A:10,A:11"')) 'example: -i "A:10,A:11"'))
group.add_argument(
"-t", "--thermophile", action="append", dest="thermophiles",
help=("defining a thermophile filename; usually used in "
"'alignment-mutations'"))
group.add_argument(
"-a", "--alignment", action="append", dest="alignment",
help=("alignment file connecting <filename> and <thermophile> "
"[<thermophile>.pir]"))
group.add_argument(
"-m", "--mutation", action="append", dest="mutations",
help=("specifying mutation labels which is used to modify "
"<filename> according to, e.g. N25R/N181D"))
group.add_argument( group.add_argument(
"--version", action="version", version=f"%(prog)s {propka.__version__}") "--version", action="version", version=f"%(prog)s {propka.__version__}")
group.add_argument( group.add_argument(
@@ -311,16 +294,6 @@ def build_parser(parser=None):
default=(0.0, 14.0, 0.1), default=(0.0, 14.0, 0.1),
help=("setting the pH-grid to calculate e.g. stability " help=("setting the pH-grid to calculate e.g. stability "
"related properties [0.0, 14.0, 0.1]")) "related properties [0.0, 14.0, 0.1]"))
group.add_argument(
"--mutator", dest="mutator",
help=(
"setting approach for mutating <filename> "
"[alignment/scwrl/jackal]"
)
)
group.add_argument(
"--mutator-option", dest="mutator_options", action="append",
help="setting property for mutator [e.g. type=\"side-chain\"]")
group.add_argument( group.add_argument(
"-d", "--display-coupled-residues", dest="display_coupled_residues", "-d", "--display-coupled-residues", dest="display_coupled_residues",
action="store_true", action="store_true",

View File

@@ -14,7 +14,7 @@ from datetime import date
from decimal import Decimal from decimal import Decimal
from os import PathLike from os import PathLike
from pathlib import Path from pathlib import Path
from typing import IO, AnyStr, List, NoReturn, Optional, Union, TYPE_CHECKING from typing import IO, AnyStr, List, Optional, Union, TYPE_CHECKING
import warnings import warnings
from .parameters import Parameters from .parameters import Parameters
@@ -52,20 +52,6 @@ def open_file_for_writing(input_file: _TextIOSource) -> IO[str]:
return input_file return input_file
def write_file(filename, lines):
"""Writes a new file.
Args:
filename: name of file
lines: lines to write to file
"""
warnings.warn("unused and untested by propka")
file_ = open_file_for_writing(filename)
for line in lines:
file_.write("{0:s}\n".format(line))
file_.close()
def print_header(): def print_header():
"""Print header section of output.""" """Print header section of output."""
str_ = "{0:s}\n".format(get_propka_header()) str_ = "{0:s}\n".format(get_propka_header())
@@ -74,46 +60,6 @@ def print_header():
_LOGGER.info("\n%s", str_) _LOGGER.info("\n%s", str_)
def write_pdb_for_protein(
protein, pdbfile=None, filename=None, include_hydrogens=False, _=None):
"""Write a residue to the new PDB file.
Args:
protein: protein object
pdbfile: PDB file
filename: file to write to
include_hydrogens: Boolean indicating whether to include hydrogens
options: options object
"""
raise NotImplementedError("unused")
if pdbfile is None:
# opening file if not given
if filename is None:
filename = "{0:s}.pdb".format(protein.name)
# TODO - this would be better as a context manager
pdbfile = open(filename, 'w')
_LOGGER.info("writing pdbfile {0:s}".format(filename))
close_file = True
else:
# don't close the file, it was opened in a different place
close_file = False
numb = 0
for chain in protein.chains:
for residue in chain.residues:
if residue.res_name not in ["N+ ", "C- "]:
for atom in residue.atoms:
if (not include_hydrogens) and atom.name[0] == "H":
# don't print
pass
else:
numb += 1
line = atom.make_pdb_line2(numb=numb)
line += "\n"
pdbfile.write(line)
if close_file:
pdbfile.close()
def write_pdb_for_conformation(conformation: "ConformationContainer", def write_pdb_for_conformation(conformation: "ConformationContainer",
filename: _PathArg): filename: _PathArg):
"""Write PDB conformation to a file. """Write PDB conformation to a file.
@@ -168,39 +114,6 @@ def write_pka(protein: "MolecularContainer",
Path(filename).write_text(str_, encoding="utf-8") Path(filename).write_text(str_, encoding="utf-8")
def print_tm_profile(protein: NoReturn, reference="neutral", window=[0., 14., 1.],
__=[0., 0.], tms=None, ref=None, _=False,
options=None):
"""Print Tm profile.
I think Tm refers to the denaturation temperature.
Args:
protein: protein object
reference: reference state
window: pH window [min, max, step]
__: temperature range [min, max]
tms: TODO - figure this out
ref: TODO - figure this out (probably reference state?)
_: Boolean for verbosity
options: options object
"""
raise NotImplementedError("unused")
profile = protein.getTmProfile(
reference=reference, grid=[0., 14., 0.1], tms=tms, ref=ref,
options=options)
if profile is None:
str_ = "Could not determine Tm-profile\n"
else:
str_ = " suggested Tm-profile for {0:s}\n".format(protein.name)
for (ph, tm_) in profile:
if (ph >= window[0] and ph <= window[1]
and (ph % window[2] < 0.01
or ph % window[2] > 0.99*window[2])):
str_ += "{0:>6.2f}{1:>10.2f}\n".format(ph, tm_)
_LOGGER.info(str_)
def print_result(protein: "MolecularContainer", conformation: str, parameters: Parameters): def print_result(protein: "MolecularContainer", conformation: str, parameters: Parameters):
"""Prints all resulting output from determinants and down. """Prints all resulting output from determinants and down.
@@ -371,34 +284,6 @@ def get_charge_profile_section(protein, conformation='AVR', _=None):
return str_ return str_
def write_jackal_scap_file(mutation_data=None, filename="1xxx_scap.list",
_=None):
"""Write a scap file for, i.e., generating a mutated protein
TODO - figure out what this is
"""
raise NotImplementedError("unused")
with open(filename, 'w') as file_:
for chain_id, _, res_num, code2 in mutation_data:
str_ = "{chain:s}, {num:d}, {code:s}\n".format(
chain=chain_id, num=res_num, code=code2)
file_.write(str_)
def write_scwrl_sequence_file(sequence, filename="x-ray.seq", _=None):
"""Write a scwrl sequence file for, e.g., generating a mutated protein
TODO - figure out what this is
"""
warnings.warn("unused and untested by propka")
with open(filename, 'w') as file_:
start = 0
while len(sequence[start:]) > 60:
file_.write("{0:s}s\n".format(sequence[start:start+60]))
start += 60
file_.write("{0:s}\n".format(sequence[start:]))
def get_propka_header(): def get_propka_header():
"""Create the header. """Create the header.

View File

@@ -118,13 +118,10 @@ class Parameters:
CYS_CYS_exception: float = 3.60 CYS_CYS_exception: float = 3.60
min_ligand_model_pka: float = -10.0 min_ligand_model_pka: float = -10.0
max_ligand_model_pka: float = 20.0 max_ligand_model_pka: float = 20.0
# include_H_in_interactions: NoReturn = None
coupling_max_number_of_bonds: int = 3 coupling_max_number_of_bonds: int = 3
min_bond_distance_for_hydrogen_bonds: int = 4 min_bond_distance_for_hydrogen_bonds: int = 4
# coupling_penalty: NoReturn = None
shared_determinants: _T_BOOL = False shared_determinants: _T_BOOL = False
common_charge_centre: _T_BOOL = False common_charge_centre: _T_BOOL = False
# hide_penalised_group: NoReturn = None
remove_penalised_group: _T_BOOL = True remove_penalised_group: _T_BOOL = True
max_intrinsic_pka_diff: float = 2.0 max_intrinsic_pka_diff: float = 2.0
min_interaction_energy: float = 0.5 min_interaction_energy: float = 0.5