From 9ea6d8815de6356b0973c86aeacf673be5bc9ab7 Mon Sep 17 00:00:00 2001 From: Thomas Holder Date: Thu, 21 Dec 2023 22:24:29 +0100 Subject: [PATCH] Remove some unused code - Remove all code which was previously marked with `NotImplementedError("unused")`. - Remove unsued command line arguments --- docs/source/changelog.rst | 11 +++ docs/source/command.rst | 29 +------- propka/atom.py | 54 +------------- propka/bonds.py | 88 ----------------------- propka/conformation_container.py | 14 +--- propka/group.py | 44 +----------- propka/lib.py | 27 ------- propka/output.py | 117 +------------------------------ propka/parameters.py | 3 - 9 files changed, 17 insertions(+), 370 deletions(-) diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 62aed47..6011b8f 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -2,6 +2,17 @@ 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 ======= diff --git a/docs/source/command.rst b/docs/source/command.rst index 86476b9..f5527d4 100644 --- a/docs/source/command.rst +++ b/docs/source/command.rst @@ -10,9 +10,9 @@ PROPKA predicts the pKa values of ionizable groups in proteins and protein-ligand complexes based in the 3D structure. The :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] - [-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 @@ -47,21 +47,6 @@ protein-ligand complexes based in the 3D structure. The should be a comma-separated list of "chain:resnum" 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 and - [.pir] (default: None) - -.. option:: -m MUTATIONS, --mutation MUTATIONS - - specifying mutation labels which is used to modify - according to, e.g. N25R/N181D (default: None) - .. option:: --version 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 properties (default: (0.0, 14.0, 0.1)) -.. option:: --mutator MUTATOR - - setting approach for mutating - [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 Displays alternative pKa values due to coupling of diff --git a/propka/atom.py b/propka/atom.py index 0cca0e1..e9f01ff 100644 --- a/propka/atom.py +++ b/propka/atom.py @@ -7,8 +7,7 @@ The :class:`Atom` class contains all atom information found in the PDB file. """ import string -from typing import cast, List, NoReturn, Optional, TYPE_CHECKING -import warnings +from typing import List, Optional, TYPE_CHECKING from propka.lib import make_tidy_atom_label from . import hybrid36 @@ -46,7 +45,6 @@ class Atom: group: Optional["Group"] = None group_type: Optional[str] = None cysteine_bridge: bool = False - residue: NoReturn = None # type: ignore[assignment] conformation_container: Optional["ConformationContainer"] = None molecular_container: Optional["MolecularContainer"] = None is_protonated: bool = False @@ -87,7 +85,6 @@ class Atom: Args: 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.set_properties(line) 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)) 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): """Returns a 'tidier' atom label for printing the new pdbfile @@ -353,13 +311,3 @@ class Atom: def __str__(self): """Return an undefined-format string version of this atom.""" 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 diff --git a/propka/bonds.py b/propka/bonds.py index 9bc00c0..70d4b21 100644 --- a/propka/bonds.py +++ b/propka/bonds.py @@ -87,63 +87,6 @@ class BondMaker: self.backbone_atoms = list(self.intra_residue_backbone_bonds.keys()) 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): """Look for bonds for terminal oxygen. @@ -423,34 +366,3 @@ class BondMaker: atom2.bonded_atoms.append(atom1) if atom2 not in atom1.bonded_atoms: 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) diff --git a/propka/conformation_container.py b/propka/conformation_container.py index 27601c4..be89b04 100644 --- a/propka/conformation_container.py +++ b/propka/conformation_container.py @@ -6,7 +6,7 @@ Container data structure for molecular conformations. """ import logging 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.version import Version @@ -497,18 +497,6 @@ class ConformationContainer: group for group in self.groups 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"]: """Get atoms associated with ligands. diff --git a/propka/group.py b/propka/group.py index 4ff702c..cfad25a 100644 --- a/propka/group.py +++ b/propka/group.py @@ -11,7 +11,7 @@ Routines and classes for storing groups important to PROPKA calculations. """ import logging import math -from typing import cast, Dict, Iterable, List, NoReturn, Optional +from typing import Dict, List, Optional import propka.ligand from propka.parameters import Parameters @@ -119,8 +119,6 @@ class Group: fmt = "{type:<3s}{name:>4s}{chain:>2s}" self.label = fmt.format( 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: """Couple this group with another group. @@ -162,46 +160,6 @@ class Group: """ 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): """Needed for creating sets of groups.""" if self.atom.type == 'atom': diff --git a/propka/lib.py b/propka/lib.py index 17dfc86..65a4ee3 100644 --- a/propka/lib.py +++ b/propka/lib.py @@ -30,7 +30,6 @@ EXPECTED_ATOM_NUMBERS = {'ALA': 5, 'ARG': 11, 'ASN': 8, 'ASP': 8, 'CYS': 6, class Options: # Note: All the "NoReturn" members appear to be unused - alignment: NoReturn # Optional[List[str]] chains: Optional[List[str]] display_coupled_residues: bool = False filenames: List[str] # List[Path]? @@ -38,15 +37,11 @@ class Options: input_pdb: str # Path? keep_protons: bool = False 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 parameters: Path protonate_all: bool = False reference: NoReturn # str = 'neutral' reuse_ligand_mol2_file: bool = False # only used by unused function - thermophiles: NoReturn # Optional[List[str]] titrate_only: Optional[List[_T_RESIDUE_TUPLE]] 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 ' 'be a comma-separated list of "chain:resnum" values; for ' '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 and " - "[.pir]")) - group.add_argument( - "-m", "--mutation", action="append", dest="mutations", - help=("specifying mutation labels which is used to modify " - " according to, e.g. N25R/N181D")) group.add_argument( "--version", action="version", version=f"%(prog)s {propka.__version__}") group.add_argument( @@ -311,16 +294,6 @@ def build_parser(parser=None): default=(0.0, 14.0, 0.1), help=("setting the pH-grid to calculate e.g. stability " "related properties [0.0, 14.0, 0.1]")) - group.add_argument( - "--mutator", dest="mutator", - help=( - "setting approach for mutating " - "[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( "-d", "--display-coupled-residues", dest="display_coupled_residues", action="store_true", diff --git a/propka/output.py b/propka/output.py index d9d8617..d124e6e 100644 --- a/propka/output.py +++ b/propka/output.py @@ -14,7 +14,7 @@ from datetime import date from decimal import Decimal from os import PathLike 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 from .parameters import Parameters @@ -52,20 +52,6 @@ def open_file_for_writing(input_file: _TextIOSource) -> IO[str]: 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(): """Print header section of output.""" str_ = "{0:s}\n".format(get_propka_header()) @@ -74,46 +60,6 @@ def print_header(): _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", filename: _PathArg): """Write PDB conformation to a file. @@ -168,39 +114,6 @@ def write_pka(protein: "MolecularContainer", 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): """Prints all resulting output from determinants and down. @@ -371,34 +284,6 @@ def get_charge_profile_section(protein, conformation='AVR', _=None): 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(): """Create the header. diff --git a/propka/parameters.py b/propka/parameters.py index 654b3fa..678a227 100644 --- a/propka/parameters.py +++ b/propka/parameters.py @@ -118,13 +118,10 @@ class Parameters: CYS_CYS_exception: float = 3.60 min_ligand_model_pka: float = -10.0 max_ligand_model_pka: float = 20.0 - # include_H_in_interactions: NoReturn = None coupling_max_number_of_bonds: int = 3 min_bond_distance_for_hydrogen_bonds: int = 4 - # coupling_penalty: NoReturn = None shared_determinants: _T_BOOL = False common_charge_centre: _T_BOOL = False - # hide_penalised_group: NoReturn = None remove_penalised_group: _T_BOOL = True max_intrinsic_pka_diff: float = 2.0 min_interaction_energy: float = 0.5