From 25d0172a163992fd9cc5958e92c29a519e3e5714 Mon Sep 17 00:00:00 2001 From: yokochi47 Date: Thu, 16 Jan 2025 21:32:22 +0900 Subject: [PATCH] Minor code refactoring --- wwpdb/utils/nmr/ChemCompUtil.py | 8 +- wwpdb/utils/nmr/CifToNmrStar.py | 37 +++-- wwpdb/utils/nmr/NmrDpReport.py | 2 +- wwpdb/utils/nmr/NmrDpUtility.py | 12 +- wwpdb/utils/nmr/ann/BMRBAnnTasks.py | 2 +- wwpdb/utils/nmr/ann/OneDepAnnTasks.py | 1 + wwpdb/utils/nmr/io/ChemCompIo.py | 150 +++++++++++++------- wwpdb/utils/nmr/io/CifReader.py | 74 +++++----- wwpdb/utils/nmr/io/mmCIFUtil.py | 88 ++++++++---- wwpdb/utils/nmr/mr/ParserListenerUtil.py | 10 +- wwpdb/utils/nmr/mr/XplorMRParserListener.py | 2 +- wwpdb/utils/nmr/nef/NEFTranslator.py | 4 +- wwpdb/utils/nmr/rci/RCI.py | 138 +++++++----------- 13 files changed, 291 insertions(+), 237 deletions(-) diff --git a/wwpdb/utils/nmr/ChemCompUtil.py b/wwpdb/utils/nmr/ChemCompUtil.py index 8b608d9b..72c0ddb8 100644 --- a/wwpdb/utils/nmr/ChemCompUtil.py +++ b/wwpdb/utils/nmr/ChemCompUtil.py @@ -27,14 +27,16 @@ from wwpdb.utils.nmr.io.ChemCompIo import ChemCompReader from wwpdb.utils.nmr.AlignUtil import (emptyValue, monDict3, - protonBeginCode) + protonBeginCode, + isReservedLigCode) cICc = ConfigInfoAppCc(getSiteId()) CC_CVS_PATH = cICc.get_site_cc_cvs_path() except ImportError: from nmr.io.ChemCompIo import ChemCompReader from nmr.AlignUtil import (emptyValue, monDict3, - protonBeginCode) + protonBeginCode, + isReservedLigCode) CC_CVS_PATH = os.path.dirname(__file__) + '/ligand_dict' # need to setup 'ligand_dict' CCD resource for NMR restraint processing @@ -154,7 +156,7 @@ def updateChemCompDict(self, compId: str) -> bool: @return: True for successfully update CCD information or False for the case a given comp_id does not exist in CCD """ - if compId in emptyValue: + if compId in emptyValue or isReservedLigCode(compId): return False compId = compId.upper() diff --git a/wwpdb/utils/nmr/CifToNmrStar.py b/wwpdb/utils/nmr/CifToNmrStar.py index 07386bcd..d490987b 100644 --- a/wwpdb/utils/nmr/CifToNmrStar.py +++ b/wwpdb/utils/nmr/CifToNmrStar.py @@ -4,11 +4,11 @@ # # Updates: # 13-Oct-2021 M. Yokochi - code revision according to PEP8 using Pylint (DAOTHER-7389, issue #5) -# 20-Apr-2022 M. Yokochi - enable to fix broken data block order of CIF formatted NMR-STAR using NMR-STAR schema (DAOTHER-7407, NMR restraint remediation) +# 20-Apr-2022 M. Yokochi - enable to fix broken datablock order of CIF formatted NMR-STAR using NMR-STAR schema (DAOTHER-7407, NMR restraint remediation) # 28-Jul-2022 M. Yokochi - enable to fix format issue of CIF formatted NMR-STAR (You cannot have two loops with the same category in one saveframe. Category: '_Audit') # 27-Sep-2022 M. Yokochi - auto fill list ID and entry ID (NMR restraint remediation) # 13-Jun-2023 M. Yokochi - sort loops in a saveframe based on schema -# 30-May-2024 M. Yokochi - resolve duplication of data block/saveframe name (DAOTHER-9437) +# 30-May-2024 M. Yokochi - resolve duplication of datablock/saveframe name (DAOTHER-9437) # 25-Jun-2024 M. Yokochi - strip white spaces in a datablock name derived from the model file (DAOTHER-9511) # 07-Jan-2025 M. Yokochi - retrieve symbolic label representations (DAOTHER-1728, 9846) ## @@ -62,23 +62,20 @@ def has_key_value(d: dict, key: Any) -> bool: return False -def get_value_safe(d: Optional[dict] = None, key: Any = None) -> Any: - """ Return value of a given dictionary for a key. - @return: value for a key, None otherwise +def get_value_safe(d: Optional[Union[dict, list, tuple]] = None, key: Optional = None, default: Optional = None) -> Any: + """ Return value of a given dictionary, list, or tuple for a key. + @return: value for a key, None (by default) otherwise """ if d is None or key is None: - return None - - if key not in d: - return None + return default - return d[key] + return d.get(key, default) -def get_first_sf_tag(sf: pynmrstar.Saveframe, tag: str, default: str = '') -> str: +def get_first_sf_tag(sf: pynmrstar.Saveframe, tag: str, default: str = '') -> Any: """ Return the first value of a given saveframe tag with decoding symbol notation. - @return: The first tag value, default string otherwise. + @return: The first tag value, '' (by default) otherwise. """ if not isinstance(sf, pynmrstar.Saveframe) or tag is None: @@ -92,11 +89,14 @@ def get_first_sf_tag(sf: pynmrstar.Saveframe, tag: str, default: str = '') -> st if not isinstance(array[0], str): return array[0] - if array[0] == '$': - return default - value = array[0] + while value.startswith('$$'): + value = value[1:] + + if len(value) == 0 or value == '$': + return default + return value if len(value) < 2 or value[0] != '$' else value[1:] @@ -107,9 +107,16 @@ def set_sf_tag(sf: pynmrstar.Saveframe, tag: str, value: Any): tagNames = [t[0] for t in sf.tags] if isinstance(value, str): + if len(value) == 0: value = None + while value.startswith('$$'): + value = value[1:] + + if len(value) == 0 or value == '$': + value = None + if tag not in tagNames: sf.add_tag(tag, value) return diff --git a/wwpdb/utils/nmr/NmrDpReport.py b/wwpdb/utils/nmr/NmrDpReport.py index 543494d5..9f0b9e0d 100644 --- a/wwpdb/utils/nmr/NmrDpReport.py +++ b/wwpdb/utils/nmr/NmrDpReport.py @@ -1855,7 +1855,7 @@ def updateNonStandardResidueByExptlData(self, chain_id: str, seq_id: int, conten # if self.__verbose: # self.__lfh.write(f'+{self.__class_name__}.updateNonStandardResidueByExptlData() ++ Error - Unknown seq_id {seq_id}\n') # raise KeyError(f"+{self.__class_name__}.updateNonStandardResidueByExptlData() ++ Error - Unknown seq_id {seq_id}") - # + except StopIteration: if self.__verbose: self.__lfh.write(f'+{self.__class_name__}.updateNonStandardResidueByExptlData() ++ Error - Unknown chain_id {chain_id}') diff --git a/wwpdb/utils/nmr/NmrDpUtility.py b/wwpdb/utils/nmr/NmrDpUtility.py index 736a2414..c66f692b 100644 --- a/wwpdb/utils/nmr/NmrDpUtility.py +++ b/wwpdb/utils/nmr/NmrDpUtility.py @@ -10591,7 +10591,7 @@ def __detectContentSubTypeOfLegacyMr(self) -> bool: s = re.split('[ ()]', _line) - _t_lower = "" + _t_lower = '' for t in s: @@ -10678,7 +10678,7 @@ def __detectContentSubTypeOfLegacyMr(self) -> bool: s = re.split('[ ()=]', _line) - _t_lower = "" + _t_lower = '' for t in s: @@ -11740,7 +11740,7 @@ def __detectContentSubTypeOfLegacyMr(self) -> bool: if not is_aux_amb and not is_aux_gro and not is_aux_cha and not has_chem_shift and not has_dist_restraint and not has_dihed_restraint and not has_rdc_restraint\ and not has_plane_restraint and not has_hbond_restraint and not has_ssbond_restraint and not valid: - hint = "" + hint = '' if len(concat_nmr_restraint_names(content_subtype)) == 0: if file_type in ('nm-res-xpl', 'nm-res-cns') and not has_rdc_origins: hint = 'assign ( segid $ and resid # and name $ ) ( segid $ and resid # and name $ ) #.# #.# #.#' @@ -11762,7 +11762,7 @@ def __detectContentSubTypeOfLegacyMr(self) -> bool: elif is_aux_amb and not has_amb_coord and not has_topology: - subtype_name = "" + subtype_name = '' if has_chem_shift: subtype_name += "Assigned chemical shifts, " if has_dist_restraint: @@ -11802,7 +11802,7 @@ def __detectContentSubTypeOfLegacyMr(self) -> bool: elif is_aux_gro and not has_topology: - subtype_name = "" + subtype_name = '' if has_chem_shift: subtype_name += "Assigned chemical shifts, " if has_dist_restraint: @@ -11836,7 +11836,7 @@ def __detectContentSubTypeOfLegacyMr(self) -> bool: elif is_aux_cha and not has_topology: - subtype_name = "" + subtype_name = '' if has_chem_shift: subtype_name += "Assigned chemical shifts, " if has_dist_restraint: diff --git a/wwpdb/utils/nmr/ann/BMRBAnnTasks.py b/wwpdb/utils/nmr/ann/BMRBAnnTasks.py index 06d4577f..9d53f66f 100644 --- a/wwpdb/utils/nmr/ann/BMRBAnnTasks.py +++ b/wwpdb/utils/nmr/ann/BMRBAnnTasks.py @@ -11,9 +11,9 @@ import copy import pynmrstar -from typing import IO, List, Optional from packaging import version from operator import itemgetter +from typing import IO, List, Optional try: from wwpdb.utils.nmr.ChemCompUtil import ChemCompUtil diff --git a/wwpdb/utils/nmr/ann/OneDepAnnTasks.py b/wwpdb/utils/nmr/ann/OneDepAnnTasks.py index ccf580b8..e48f3328 100644 --- a/wwpdb/utils/nmr/ann/OneDepAnnTasks.py +++ b/wwpdb/utils/nmr/ann/OneDepAnnTasks.py @@ -14,6 +14,7 @@ import collections from typing import IO, List + from wwpdb.utils.align.alignlib import PairwiseAlign # pylint: disable=no-name-in-module try: diff --git a/wwpdb/utils/nmr/io/ChemCompIo.py b/wwpdb/utils/nmr/io/ChemCompIo.py index b15cbb28..7ab879da 100644 --- a/wwpdb/utils/nmr/io/ChemCompIo.py +++ b/wwpdb/utils/nmr/io/ChemCompIo.py @@ -4,13 +4,11 @@ # # Update: # 06-Aug-2010 - jdw - Generalized construction of methods to apply to any category -# Add accessors for lists of dictionaries. +# Add accessors for lists of dictionaries # 12-May-2011 - rps - Added check for None when asking for category Object in __getDataList() # 2012-10-24 RPS Updated to reflect reorganization of modules in pdbx packages ## -""" -A collection of classes supporting chemical component dictionary data files. - +""" A collection of classes supporting chemical component dictionary data files """ __docformat__ = "restructuredtext en" __author__ = "John Westbrook" @@ -27,9 +25,18 @@ from typing import IO, List, Optional +try: + from wwpdb.utils.nmr.AlignUtil import (emptyValue, + isReservedLigCode) +except ImportError: + from nmr.AlignUtil import (emptyValue, + isReservedLigCode) + + class ChemCompReader: - """ Accessor methods chemical component definition data files. + """ Accessor methods chemical component definition data files """ + def __init__(self, verbose: bool = True, log: IO = sys.stdout): self.__class_name__ = self.__class__.__name__ @@ -41,7 +48,7 @@ def __init__(self, verbose: bool = True, log: IO = sys.stdout): self.__topCachePath = None self.__ccU = None self.__filePath = None - # + self.__cDict = { 'chem_comp': [ ('_chem_comp.id', '%s', 'str', ''), @@ -118,70 +125,105 @@ def __init__(self, verbose: bool = True, log: IO = sys.stdout): } def setCachePath(self, topCachePath: str = '/data/components/ligand-dict-v4'): - """ Set the top file tree of chemical component dictionary. + """ Set the top file tree of chemical component dictionary """ + self.__topCachePath = topCachePath def setCompId(self, compId: str) -> bool: - """ Set chemical component definition data file path of the input chemical component. + """ Set chemical component definition data file path of the input chemical component """ + + if compId in emptyValue: + return False + self.__ccU = compId.upper() - hashd = self.__getCcdHash(self.__ccU) - self.__filePath = os.path.join(self.__topCachePath, hashd, self.__ccU, self.__ccU + '.cif') + + hashKey = self.__ccU[-2:] if len(self.__ccU) > 3 else self.__ccU[0] + + self.__filePath = os.path.join(self.__topCachePath, hashKey, self.__ccU, self.__ccU + '.cif') + if not os.access(self.__filePath, os.R_OK): - if self.__verbose: - self.__lfh.write(f"+{self.__class_name__}.getCompId() ++ Error - Missing file {self.__filePath}\n") + + if self.__verbose and len(compId) in (3, 5) and compId[-1] not in ('+', '-')\ + and not isReservedLigCode(compId): + self.__lfh.write(f"+{self.__class_name__}.setCompId() ++ Error - Missing file {self.__filePath}\n") + return False + return True def setFilePath(self, filePath: str, compId: Optional[str] = None) -> bool: - """ Set data file path directory with chemical component ID. + """ Set data file path directory with chemical component ID """ + try: - if compId is not None: - self.__ccU = str(compId).upper() + + if compId in emptyValue: + return False + + self.__ccU = str(compId).upper() + self.__filePath = filePath + if not os.access(self.__filePath, os.R_OK): - if self.__verbose: + + if self.__verbose and len(compId) in (3, 5) and compId[-1] not in ('+', '-')\ + and not isReservedLigCode(compId): self.__lfh.write(f"+{self.__class_name__}.setFilePath() ++ Error - Missing file {self.__filePath}\n") + return False + return True - except Exception: + + except Exception as e: + if self.__verbose: - self.__lfh.write(f"+{self.__class_name__}.setFilePath() ++ Error - Missing file {self.__filePath}\n") + self.__lfh.write(f"+{self.__class_name__}.setFilePath() ++ Error - Set {self.__filePath} failed {str(e)}\n") + return False def getAtomList(self) -> List[list]: - """ Get a list of list of data from the chem_comp_atom category. + """ Get a list of list of data from the chem_comp_atom category """ + self.__getComp() + return self.__getDataList(catName='chem_comp_atom') def getBonds(self) -> List[list]: - """ Get a list of list of data from the chem_comp_bond category. + """ Get a list of list of data from the chem_comp_bond category """ + self.__getComp() + return self.__getDataList(catName='chem_comp_bond') def getChemCompDict(self) -> dict: - """ Get a list of dictionaries of a chem_comp category. + """ Get a list of dictionaries of a chem_comp category """ + try: + self.__getComp() dL = self.__getDictList(catName='chem_comp') + return dL[0] + except Exception: return {} def __getComp(self) -> bool: - """ Get the definition data for the input chemical component. + """ Get the definition data for the input chemical component Data is read from chemical component definition file stored in the organization - of CVS repository for chemical components. - - Returns True for success or False otherwise. + of CVS repository for chemical components + @return: True for success or False otherwise """ + try: + block = self.__getDataBlock(self.__filePath, self.__ccU) + return self.__setDataBlock(block) except Exception: @@ -190,22 +232,27 @@ def __getComp(self) -> bool: def __getDataBlock(self, filePath: str, blockId: Optional[str] = None): """ Worker method to read chemical component definition file and set the target datablock - corresponding to the target chemical component. - If no blockId is provided return the first data block. + corresponding to the target chemical component + @return: the first datablock if no blockId is provided """ + try: + with open(filePath, 'r', encoding='utf-8') as ifh: myBlockList = [] pRd = PdbxReader(ifh) pRd.read(myBlockList) if blockId is not None: + for block in myBlockList: if (block.getType() == 'data' and block.getName() == blockId): if self.__verbose and self.__debug: block.printIt(self.__lfh) return block + else: + for block in myBlockList: if block.getType() == 'data': if self.__verbose and self.__debug: @@ -213,21 +260,26 @@ def __getDataBlock(self, filePath: str, blockId: Optional[str] = None): return block return None + except Exception: traceback.print_exc(file=self.__lfh) return None def __setDataBlock(self, dataBlock) -> bool: - """ Assigns the input data block as the active internal data block containing the - target chemical component definition. + """ Assigns the input datablock as the active internal datablock containing the + target chemical component definition """ + ok = False + try: + if dataBlock.getType() == 'data': self.__dBlock = dataBlock ok = True else: self.__dBlock = None + except Exception: pass @@ -236,27 +288,26 @@ def __setDataBlock(self, dataBlock) -> bool: def __getDictList(self, catName: str = 'chem_comp') -> List[dict]: """ Return a list of dictionaries of the input category """ - # Get category object - from current data block + + # Get category object - from current datablock itTupList = self.__cDict[catName] catObj = self.__dBlock.getObj(catName) - # - # Get column name index. - # + + # Get column name index itDict = {} itNameList = catObj.getItemNameList() for idxIt, itName in enumerate(itNameList): itDict[itName] = idxIt - # + # Find the mapping to the local category definition - # colDict = {} - # + for _ii, itTup in enumerate(itTupList): if itTup[0] in itDict: colDict[itTup[0]] = itDict[itTup[0]] else: colDict[itTup[0]] = -1 - # + rowList = catObj.getRowList() dList = [] for row in rowList: @@ -272,17 +323,19 @@ def __getDictList(self, catName: str = 'chem_comp') -> List[dict]: def __getDataList(self, catName: str = 'chem_comp_bond') -> List[list]: """ Return a list a list of data from the input category including - data types and default value replacement. + data types and default value replacement """ + itTupList = self.__cDict[catName] dataList = [] catObj = self.__dBlock.getObj(catName) + if catObj is not None: itDict = {} itNameList = catObj.getItemNameList() for idxIt, itName in enumerate(itNameList): itDict[itName] = idxIt - # + colTupList = [] # (column index of data or -1, type name, [default value]) for _ii, itTup in enumerate(itTupList): @@ -290,7 +343,7 @@ def __getDataList(self, catName: str = 'chem_comp_bond') -> List[list]: colTupList.append((itDict[itTup[0]], itTup[2], itTup[3])) else: colTupList.append((-1, itTup[2], itTup[3])) - # + rowList = catObj.getRowList() for row in rowList: @@ -307,15 +360,14 @@ def __getDataList(self, catName: str = 'chem_comp_bond') -> List[list]: return dataList def __applyType(self, ctype: str, default, val): # pylint: disable=no-self-use - """ Apply type conversion to the input value and assign default values to - missing values. + """ Apply type conversion to the input value and assign default values to missing values """ + tval = val if val is None: tval = default if isinstance(tval, str) and (len(tval) < 1 or tval in ('.', '?')): tval = default - if ctype == "int": return int(str(tval)) if ctype == "float": @@ -324,15 +376,3 @@ def __applyType(self, ctype: str, default, val): # pylint: disable=no-self-use return str(tval) return tval - - def __getCcdHash(self, idCode: str) -> str: # pylint: disable=no-self-use - """Returns the hash code for a CCD id. Currently first letter""" - if not idCode: - return None - - if len(idCode) > 3: - hash_key = idCode.upper()[-2:] - else: - hash_key = idCode.upper()[0] - - return hash_key diff --git a/wwpdb/utils/nmr/io/CifReader.py b/wwpdb/utils/nmr/io/CifReader.py index 68b50e89..d96e24a9 100644 --- a/wwpdb/utils/nmr/io/CifReader.py +++ b/wwpdb/utils/nmr/io/CifReader.py @@ -35,7 +35,7 @@ # 10-Sep-2024 my - ignore identical polymer sequence extensions within polynucleotide multiplexes (DAOTHER-9674) # 18-Sep-2024 my - add 'starts-with-alnum' item type (DAOTHER-9694) ## -""" A collection of classes for parsing CIF files. +""" A collection of classes for parsing CIF files """ import sys @@ -67,10 +67,10 @@ # must be one of reorder_hungarian, reorder_brute, reorder_distance, None REORDER_METHOD = reorder_hungarian # scan through reflections in planes (e.g. Y transformed to -Y -> X, -Y, Z) and axis changes, -# (e.g. X and Z coords exchanged -> Z, Y, X). This will affect stereo-chemistry. +# (e.g. X and Z coords exchanged -> Z, Y, X). This will affect stereo-chemistry USE_REFLECTIONS = False # scan through reflections in planes (e.g. Y transformed to -Y -> X, -Y, Z) and axis changes, -# (e.g. X and Z coords exchanged -> Z, Y, X). Stereo-chemistry will be kept. +# (e.g. X and Z coords exchanged -> Z, Y, X). Stereo-chemistry will be kept USE_REFLECTIONS_KEEP_STEREO = False REORDER = False @@ -85,7 +85,7 @@ def M(axis: list, theta: float) -> list: - """ Return the rotation matrix associated with counterclockwise rotation about the given axis by theta radians. + """ Return the rotation matrix associated with counterclockwise rotation about the given axis by theta radians """ axis = np.asarray(axis) @@ -101,15 +101,15 @@ def M(axis: list, theta: float) -> list: def to_np_array(a: dict) -> list: - """ Return Numpy array of a given Cartesian coordinate in {'x': float, 'y': float, 'z': float} format. + """ Return Numpy array of a given Cartesian coordinate in {'x': float, 'y': float, 'z': float} format """ return np.asarray([a['x'], a['y'], a['z']], dtype=float) def get_coordinates(p: list) -> [list, list]: - """ Convert list of atoms for RMSD calculation. - @return: a vector set of the coordinates. + """ Convert list of atoms for RMSD calculation + @return: a vector set of the coordinates """ V = [] @@ -128,7 +128,7 @@ def get_coordinates(p: list) -> [list, list]: def calculate_rmsd(p: list, q: list) -> float: - """ Calculate RMSD of two coordinates. + """ Calculate RMSD of two coordinates @return: RMSD value """ @@ -207,7 +207,7 @@ def calculate_uninstanced_coord(p_coord: list, q_coord: list, s_coord: list) -> class CifReader: - """ Accessor methods for parsing CIF files. + """ Accessor methods for parsing CIF files """ def __init__(self, verbose: bool = True, log: IO = sys.stdout, @@ -231,10 +231,10 @@ def __init__(self, verbose: bool = True, log: IO = sys.stdout, # current working directory path self.__dirPath = None - # data block list + # datablock list self.__dBlockList = None - # the primary data block + # the primary datablock self.__dBlock = None # hash code of current cif file @@ -281,8 +281,8 @@ def __init__(self, verbose: bool = True, log: IO = sys.stdout, self.__rmsd_overlaid_exactly = 0.01 def parse(self, filePath: str, dirPath: Optional[str] = None) -> bool: - """ Parse CIF file, and set internal active data block if possible. - @return: True for success or False otherwise. + """ Parse CIF file, and set internal active datablock if possible + @return: True for success or False otherwise """ if dirPath is not None: @@ -299,7 +299,7 @@ def parse(self, filePath: str, dirPath: Optional[str] = None) -> bool: if not os.access(self.__filePath, os.R_OK): if self.__verbose: - self.__lfh.write(f"+{self.__class_name__}.parse() ++ Error - Missing file {self.__filePath}\n") + self.__lfh.write(f"+{self.__class_name__} ++ Error - Missing file {self.__filePath}\n") return False if self.__use_cache: @@ -308,15 +308,15 @@ def parse(self, filePath: str, dirPath: Optional[str] = None) -> bool: return self.__setDataBlock(self.__getDataBlockFromFile()) - except Exception: - if self.__verbose: - self.__lfh.write(f"+{self.__class_name__}.parse() ++ Error - Missing file {self.__filePath}\n") + except Exception as e: + if self.__verbose and 'loop_ declaration outside of data_ block or save_ frame' not in str(e): + self.__lfh.write(f"+{self.__class_name__} ++ Error - Parse {self.__filePath} failed {str(e)}\n") return False def __getDataBlockFromFile(self, blockId: Optional[str] = None): - """ Worker method to read cif file and set the target datablock. - If no blockId is provided return the first data block. - @return: target data block + """ Worker method to read cif file and set the target datablock + If no blockId is provided return the first datablock + @return: target datablock """ if self.__use_cache: @@ -361,8 +361,8 @@ def __getDataBlockFromFile(self, blockId: Optional[str] = None): return None def __setDataBlock(self, dataBlock: Optional[str] = None) -> bool: - """ Assigns the input data block as the active internal data block. - @return: True for success or False otherwise. + """ Assigns the input datablock as the active internal datablock + @return: True for success or False otherwise """ ok = False @@ -384,13 +384,13 @@ def __setDataBlock(self, dataBlock: Optional[str] = None) -> bool: return ok def getFilePath(self) -> str: - """ Return cif file path. + """ Return cif file path """ return self.__filePath def getHashCode(self) -> str: - """ Return hash code of the cif file. + """ Return hash code of the cif file """ if self.__hashCode is None: @@ -400,15 +400,15 @@ def getHashCode(self) -> str: return self.__hashCode def getDataBlockList(self) -> list: - """ Return whole list of datablock. + """ Return whole list of datablock """ return self.__dBlockList def getDataBlock(self, blockId: Optional[str] = None): - """ Return target datablock. - Return None in case current blockId does not exist or no blockId does not match. - @return: target data block + """ Return target datablock + Return None in case current blockId does not exist or no blockId does not match + @return: target datablock """ if self.__dBlock is None or self.__dBlock.getType() != 'data': @@ -422,7 +422,7 @@ def getDataBlock(self, blockId: Optional[str] = None): return dBlock if self.__setDataBlock(dBlock) else None def hasCategory(self, catName: str, blockId: Optional[str] = None) -> bool: - """ Return whether a given category exists. + """ Return whether a given category exists """ if blockId is not None and self.__dBlock is not None and self.__dBlock.getName() != blockId: @@ -434,7 +434,7 @@ def hasCategory(self, catName: str, blockId: Optional[str] = None) -> bool: return catName in self.__dBlock.getObjNameList() def hasItem(self, catName: str, itName: str, blockId: Optional[str] = None) -> bool: - """ Return whether a given item exists in a category. + """ Return whether a given item exists in a category """ if blockId is not None and self.__dBlock is not None and self.__dBlock.getName() != blockId: @@ -454,7 +454,7 @@ def hasItem(self, catName: str, itName: str, blockId: Optional[str] = None) -> b return itName in [name[len_catName:] for name in catObj.getItemNameList()] def getItemTags(self, catName: str, blockId: Optional[str] = None) -> List[str]: - """ Return item tag names of a given category. + """ Return item tag names of a given category """ if blockId is not None and self.__dBlock is not None and self.__dBlock.getName() != blockId: @@ -474,7 +474,7 @@ def getItemTags(self, catName: str, blockId: Optional[str] = None) -> List[str]: return [name[len_catName:] for name in catObj.getItemNameList()] def getRowLength(self, catName: str, blockId: Optional[str] = None) -> int: - """ Return length of rows of a given category. + """ Return length of rows of a given category """ if blockId is not None and self.__dBlock is not None and self.__dBlock.getName() != blockId: @@ -492,7 +492,7 @@ def getRowLength(self, catName: str, blockId: Optional[str] = None) -> int: return 0 def getRowList(self, catName: str, blockId: Optional[str] = None) -> List[list]: - """ Return length of rows of a given category. + """ Return length of rows of a given category """ if blockId is not None and self.__dBlock is not None and self.__dBlock.getName() != blockId: @@ -510,7 +510,7 @@ def getRowList(self, catName: str, blockId: Optional[str] = None) -> List[list]: return [] def getDictList(self, catName: str, blockId: Optional[str] = None) -> List[dict]: - """ Return a list of dictionaries of a given category. + """ Return a list of dictionaries of a given category """ dList = [] @@ -546,7 +546,7 @@ def getDictList(self, catName: str, blockId: Optional[str] = None) -> List[dict] def getDictListWithFilter(self, catName: str, dataItems: List[dict], filterItems: Optional[List[dict]] = None, blockId: Optional[str] = None) -> List[dict]: - """ Return a list of dictionaries of a given category with filter. + """ Return a list of dictionaries of a given category with filter """ dataNames = [d['name'] for d in dataItems] @@ -1354,7 +1354,7 @@ def getPolymerSequence(self, catName: str, keyItems: List[dict], return asm def __extractStructConf(self, chain_id: str, seq_ids: List[int], label_scheme: bool = True) -> List[Optional[str]]: - """ Extract structure conformational annotations. + """ Extract structure conformational annotations """ ret = [None] * len(seq_ids) @@ -1396,7 +1396,7 @@ def __extractStructConf(self, chain_id: str, seq_ids: List[int], label_scheme: b def __calculateRmsd(self, chain_ids: List[str], lengths: List[int], total_models: int = 1, eff_model_ids: Optional[List[str]] = None, atom_sites: Optional[List[dict]] = None, bb_atom_sites: Optional[List[dict]] = None, randomM: Optional[List[list]] = None) -> Tuple[Optional[List[dict]], Optional[List[dict]]]: - """ Calculate RMSD of alpha carbons/phosphates in the ensemble. + """ Calculate RMSD of alpha carbons/phosphates in the ensemble """ if atom_sites is None or bb_atom_sites is None: diff --git a/wwpdb/utils/nmr/io/mmCIFUtil.py b/wwpdb/utils/nmr/io/mmCIFUtil.py index 2bf165f3..ca45296f 100644 --- a/wwpdb/utils/nmr/io/mmCIFUtil.py +++ b/wwpdb/utils/nmr/io/mmCIFUtil.py @@ -4,8 +4,8 @@ Update: 21-August-2012 Version: 001 Initial version # Update: -# 07-Apr-2020 M. Yokochi - Re-write Zukang's version to being aware of multiple data blocks -# 30-May-2024 M. Yokochi - Resolve duplication of data block/saveframe name (DAOTHER-9437) +# 07-Apr-2020 M. Yokochi - Re-write Zukang's version to being aware of multiple datablocks +# 30-May-2024 M. Yokochi - Resolve duplication of datablock/saveframe name (DAOTHER-9437) # 16-Jan-2025 M. Yokochi - Abandon symbolic label representations in mmCIF for mutual format conversion ## """ @@ -15,6 +15,7 @@ __version__ = "V0.001" import sys +import os import copy import re @@ -32,11 +33,12 @@ def get_ext_block_name(name: str, ext: int = 1) -> str: """ Return unique block name avoiding duplication """ + return name if ext == 1 else f'{name}_{ext}' def abandon_symbolic_labels(containerList: list): - """ Abandon symbolic label representations that serve as saveframe pointers in NMR-STAR. + """ Abandon symbolic label representations that serve as saveframe pointers in NMR-STAR """ for container in containerList: @@ -61,20 +63,23 @@ class mmCIFUtil: def __init__(self, verbose: bool = False, log: IO = sys.stderr, filePath: Optional[str] = None): # pylint: disable=unused-argument self.__class_name__ = self.__class__.__name__ - # self.__verbose = verbose + self.__verbose = verbose self.__lfh = log self.__filePath = filePath self.__dataList = [] self.__dataMap = {} self.__blockNameList = [] - self.__read() - def __read(self): if not self.__filePath: return - # + try: + if not os.access(self.__filePath, os.R_OK): + if self.__verbose: + self.__lfh.write(f"+{self.__class_name__} ++ Error - Missing file {self.__filePath}\n") + return + with open(self.__filePath, 'r', encoding='utf-8') as ifh: pRd = PdbxReader(ifh) pRd.read(self.__dataList) @@ -98,27 +103,29 @@ def __read(self): break ext += 1 idx += 1 - # - # + except Exception as e: - self.__lfh.write(f"+{self.__class_name__} ++ Error - Read {self.__filePath} failed {str(e)}.\n") + if self.__verbose and 'loop_ declaration outside of data_ block or save_ frame' not in str(e): + self.__lfh.write(f"+{self.__class_name__} ++ Error - Read {self.__filePath} failed {str(e)}\n") def GetBlockIDList(self) -> List[str]: """ Return list of block ID """ + return self.__blockNameList def GetValueAndItemByBlock(self, blockName: str, catName: str, ext: int = 1) -> Tuple[List[dict], List[str]]: """ Get category values and item names """ + dList, iList = [], [] if blockName not in self.__dataMap: return dList, iList - # + catObj = self.__dataList[self.__dataMap[get_ext_block_name(blockName, ext)]].getObj(catName) if not catObj: return dList, iList - # + iList = catObj.getAttributeList() rowList = catObj.getRowList() for row in rowList: @@ -127,25 +134,28 @@ def GetValueAndItemByBlock(self, blockName: str, catName: str, ext: int = 1) -> for idxIt, itName in enumerate(iList): if row[idxIt] != "?" and row[idxIt] != ".": tD[itName] = row[idxIt] - # + if tD: dList.append(tD) - # + except IndexError: pass - # + return dList, iList def GetValue(self, blockName: str, catName: str, ext: int = 1) -> List[dict]: """ Get category values in a given Data Block and Category The results are stored in a list of dictionaries with item name as key """ + return self.GetValueAndItemByBlock(blockName, catName, ext)[0] def GetSingleValue(self, blockName: str, catName: str, itemName: str, ext: int) -> Any: """ Get the first value of a given Data Block, Category, Item """ - text = "" + + text = '' + dlist = self.GetValue(blockName, catName, ext) if dlist: if itemName in dlist[0]: @@ -155,6 +165,7 @@ def GetSingleValue(self, blockName: str, catName: str, itemName: str, ext: int) def UpdateSingleRowValue(self, blockName: str, catName: str, itemName: str, rowIndex: int, value: Any, ext: int = 1): """ Update value in single row """ + if blockName not in self.__dataMap: return @@ -162,12 +173,13 @@ def UpdateSingleRowValue(self, blockName: str, catName: str, itemName: str, rowI if not catObj: return - # + catObj.setValue(value, itemName, rowIndex) def UpdateMultipleRowsValue(self, blockName: str, catName: str, itemName: str, value: Any, ext: int = 1): """ Update value in multiple rows """ + if blockName not in self.__dataMap: return @@ -175,7 +187,7 @@ def UpdateMultipleRowsValue(self, blockName: str, catName: str, itemName: str, v if not catObj: return - # + rowNo = catObj.getRowCount() for rowIndex in range(0, rowNo): catObj.setValue(value, itemName, rowIndex) @@ -183,25 +195,30 @@ def UpdateMultipleRowsValue(self, blockName: str, catName: str, itemName: str, v def AddBlock(self, blockName: str, ext: int = 1): """ Add Data Block """ + container = DataContainer(blockName) + self.__dataMap[get_ext_block_name(blockName, ext)] = len(self.__dataList) self.__dataList.append(container) def AddCategory(self, blockName: str, catName: str, items: List[str], ext: int = 1): """ Add Category in a given Data Block """ + if blockName not in self.__dataMap: return category = DataCategory(catName) + for item in items: category.appendAttribute(item) - # + self.__dataList[self.__dataMap[get_ext_block_name(blockName, ext)]].append(category) def RemoveCategory(self, blockName: str, catName: str, ext: int = 1): """ Remove Category in a given Data Block """ + if blockName not in self.__dataMap: return @@ -217,6 +234,7 @@ def RemoveCategory(self, blockName: str, catName: str, ext: int = 1): def MoveCategoryToTop(self, blockName: str, catName: str, ext: int = 1): """ Move Category to top in a given Data Block """ + if blockName not in self.__dataMap: return @@ -242,6 +260,7 @@ def MoveCategoryToTop(self, blockName: str, catName: str, ext: int = 1): def InsertData(self, blockName: str, catName: str, dataList: list, ext: int = 1): """ Insert data in a given Data Block and Category """ + if blockName not in self.__dataMap: return @@ -249,13 +268,14 @@ def InsertData(self, blockName: str, catName: str, dataList: list, ext: int = 1) if catObj is None: return - # + for data in dataList: catObj.append(data) def ExtendCategory(self, blockName: str, catName: str, items: List[str], dataList: list, col: int = -1, ext: int = 1): """ Extend existing Category in a given Data Block """ + if blockName not in self.__dataMap: return @@ -311,6 +331,7 @@ def ExtendCategory(self, blockName: str, catName: str, items: List[str], dataLis def CopyValueInRow(self, blockName: str, catName: str, srcItems: List[str], dstItems: List[str], ext: int = 1): """ Copy value from source items to destination items """ + if srcItems is None or dstItems is None or len(srcItems) != len(dstItems): return @@ -342,9 +363,10 @@ def CopyValueInRow(self, blockName: str, catName: str, srcItems: List[str], dstI def WriteCif(self, outputFilePath: Optional[str] = None): """ Write out cif file """ + if not outputFilePath: return - # + with open(outputFilePath, 'w', encoding='utf-8') as ofh: pdbxW = PdbxWriter(ofh) pdbxW.write(self.__dataList) @@ -352,16 +374,19 @@ def WriteCif(self, outputFilePath: Optional[str] = None): def GetCategories(self) -> dict: """ Get all Categories in all Data Blocks """ + data = {} + for container in self.__dataList: blockName = container.getName() data[blockName] = container.getObjNameList() - # + return data def GetAttributes(self, blockName: str, catName: str, ext: int = 1) -> List[str]: """ Get item name in Data Block and Category """ + if blockName not in self.__dataMap: return [] @@ -369,12 +394,13 @@ def GetAttributes(self, blockName: str, catName: str, ext: int = 1) -> List[str] if not catObj: return [] - # + return catObj.getAttributeList() def GetRowLength(self, blockName: str, catName: str, ext: int = 1) -> int: - """ Return length of rows of a given category. + """ Return length of rows of a given category """ + if blockName not in self.__dataMap: return 0 @@ -382,12 +408,13 @@ def GetRowLength(self, blockName: str, catName: str, ext: int = 1) -> int: if not catObj: return 0 - # + return len(catObj.getRowList()) def GetRowList(self, blockName: str, catName: str, ext: int = 1) -> List[list]: """ Get a list of list of a geven Data Block and Category """ + if blockName not in self.__dataMap: return [] @@ -395,26 +422,29 @@ def GetRowList(self, blockName: str, catName: str, ext: int = 1) -> List[list]: if not catObj: return [] - # + return catObj.getRowList() def GetDictList(self, blockName: str, catName: str, ext: int = 1) -> dict: """ Get a list of dictionaries of a given Data Block and Category """ + dList, iList = self.GetValueAndItemByBlock(blockName, catName, ext) data = [[x.get(y) for y in iList] for x in dList] - # + return {catName: {"Items": iList, "Values": data}} def GetDataBlock(self, blockName: str, ext: int = 1) -> dict: """ Get a list of dictionaries of a given Data Block """ + data = {} + categories = self.GetCategories() if blockName not in categories: return data - # + for catName in categories[blockName]: data.update(self.GetDictList(blockName, catName, ext)) - # + return data diff --git a/wwpdb/utils/nmr/mr/ParserListenerUtil.py b/wwpdb/utils/nmr/mr/ParserListenerUtil.py index b3e41b17..269ea4f3 100644 --- a/wwpdb/utils/nmr/mr/ParserListenerUtil.py +++ b/wwpdb/utils/nmr/mr/ParserListenerUtil.py @@ -79,6 +79,7 @@ for nuc_name, iso_nums in ISOTOPE_NUMBERS_OF_NMR_OBS_NUCS.items(): for iso_num in iso_nums: ISOTOPE_NAMES_OF_NMR_OBS_NUCS.append(f'{iso_num}{nuc_name}') +ISOTOPE_NAMES_OF_NMR_OBS_NUCS = tuple(ISOTOPE_NAMES_OF_NMR_OBS_NUCS) # nucleus with half spin HALF_SPIN_NUCLEUS = ('H', 'C', 'N', 'P', 'F', 'CD') @@ -91,11 +92,13 @@ ALLOWED_ISOTOPE_NUMBERS = [] for isotopeNums in ISOTOPE_NUMBERS_OF_NMR_OBS_NUCS.values(): ALLOWED_ISOTOPE_NUMBERS.extend(isotopeNums) +ALLOWED_ISOTOPE_NUMBERS = tuple(ALLOWED_ISOTOPE_NUMBERS) WELL_KNOWN_ISOTOPE_NUMBERS = copy.copy(ISOTOPE_NUMBERS_OF_NMR_OBS_NUCS['H']) WELL_KNOWN_ISOTOPE_NUMBERS.extend(ISOTOPE_NUMBERS_OF_NMR_OBS_NUCS['C']) WELL_KNOWN_ISOTOPE_NUMBERS.extend(ISOTOPE_NUMBERS_OF_NMR_OBS_NUCS['N']) WELL_KNOWN_ISOTOPE_NUMBERS.extend(ISOTOPE_NUMBERS_OF_NMR_OBS_NUCS['P']) +WELL_KNOWN_ISOTOPE_NUMBERS = tuple(WELL_KNOWN_ISOTOPE_NUMBERS) REPRESENTATIVE_MODEL_ID = 1 @@ -273,7 +276,7 @@ XPLOR_RDC_PRINCIPAL_AXIS_NAMES = ('OO', 'X', 'Y', 'Z') -XPLOR_ORIGIN_AXIS_COLS = [0, 1, 2, 3] +XPLOR_ORIGIN_AXIS_COLS = (0, 1, 2, 3) XPLOR_NITROXIDE_NAMES = ('NO', 'NX', 'NR', 'NAI', 'OS1', 'NS1') @@ -281,7 +284,7 @@ HEME_LIKE_RES_NAMES = ('HEM', 'HEB', 'HEC', 'MH0') -LEGACY_PDB_RECORDS = ['HEADER', 'OBSLTE', 'TITLE ', 'SPLIT ', 'CAVEAT', 'COMPND', 'SOURCE', 'KEYWDS', 'EXPDTA', +LEGACY_PDB_RECORDS = ('HEADER', 'OBSLTE', 'TITLE ', 'SPLIT ', 'CAVEAT', 'COMPND', 'SOURCE', 'KEYWDS', 'EXPDTA', 'NUMMDL', 'MDLTYP', 'AUTHOR', 'REVDAT', 'SPRSDE', 'JRNL', 'REMARK', 'DBREF', 'DBREF1', 'DBREF2', 'SEQADV', 'SEQRES', 'MODRES', 'HET ', 'HETNAM', 'HETSYN', 'FORMUL', @@ -292,8 +295,7 @@ 'MTRIX1', 'MTRIX2', 'MTRIX3', 'MODEL ', 'ATOM ', 'ANISOU', 'TER ', 'HETATM', 'ENDMDL', 'CONECT', - 'MASTER' - ] + 'MASTER') CYANA_MR_FILE_EXTS = (None, 'upl', 'lol', 'aco', 'rdc', 'pcs', 'upv', 'lov', 'cco') diff --git a/wwpdb/utils/nmr/mr/XplorMRParserListener.py b/wwpdb/utils/nmr/mr/XplorMRParserListener.py index c3d5c53f..3a3c4820 100644 --- a/wwpdb/utils/nmr/mr/XplorMRParserListener.py +++ b/wwpdb/utils/nmr/mr/XplorMRParserListener.py @@ -8439,7 +8439,7 @@ def exitHbond_assign(self, ctx: XplorMRParser.Hbond_assignContext): # pylint: d self.__authToStarSeq, self.__authToOrigSeq, self.__authToInsCode, self.__offsetHolder, atom1, atom3) sf['loop'].add_data(row) - # + sf['index_id'] += 1 memberLogicCode = 'AND' row = getRow(self.__cur_subtype, sf['id'], sf['index_id'], diff --git a/wwpdb/utils/nmr/nef/NEFTranslator.py b/wwpdb/utils/nmr/nef/NEFTranslator.py index 656118af..208ff148 100644 --- a/wwpdb/utils/nmr/nef/NEFTranslator.py +++ b/wwpdb/utils/nmr/nef/NEFTranslator.py @@ -233,8 +233,8 @@ # data items in _Entity_deleted_atom category of NMR-STAR -ENTITY_DELETED_ATOM_ITEMS = ['ID', 'Entity_assembly_ID', 'Comp_index_ID', 'Comp_ID', 'Atom_ID', - 'Auth_entity_assembly_ID', 'Auth_seq_ID', 'Auth_comp_ID', 'Auth_atom_ID', 'Assembly_ID'] +ENTITY_DELETED_ATOM_ITEMS = ('ID', 'Entity_assembly_ID', 'Comp_index_ID', 'Comp_ID', 'Atom_ID', + 'Auth_entity_assembly_ID', 'Auth_seq_ID', 'Auth_comp_ID', 'Auth_atom_ID', 'Assembly_ID') # integer pattern diff --git a/wwpdb/utils/nmr/rci/RCI.py b/wwpdb/utils/nmr/rci/RCI.py index e14b4f9d..eb455e11 100644 --- a/wwpdb/utils/nmr/rci/RCI.py +++ b/wwpdb/utils/nmr/rci/RCI.py @@ -9,12 +9,13 @@ @author: Masashi Yokochi """ import sys -from math import pow, exp, log # pylint: disable=redefined-builtin - import numpy as np +from math import pow, exp, log # pylint: disable=redefined-builtin +from typing import IO, List, Tuple + -def lmean(list): # pylint: disable=redefined-builtin +def lmean(list: list) -> float: # pylint: disable=redefined-builtin """ Returns the average of the array elements. """ @@ -28,7 +29,7 @@ class RCI: """ Wrapper class for Random Coil Index calculation. """ - def __init__(self, verbose=False, log=sys.stderr): # pylint: disable=redefined-builtin,redefined-outer-name + def __init__(self, verbose: bool = False, log: IO = sys.stderr): # pylint: disable=redefined-builtin,redefined-outer-name self.__verbose = verbose self.__lfh = log @@ -118,10 +119,6 @@ def __init__(self, verbose=False, log=sys.stderr): # pylint: disable=redefined- self.miss_ass = 1 self.scale = 1 - self.__setup__() - - def __setup__(self): - if self.function_flag == 1: self.floor_value = 0.6 if self.function_flag == 3: @@ -6004,7 +6001,7 @@ def __setup__(self): self.__coef_mean = self.__mean_coef() - def __mean_coef(self): + def __mean_coef(self) -> float: """ Function to calculate mean weighting coefficient. """ @@ -6015,7 +6012,7 @@ def __mean_coef(self): return lmean(l_coef_list) - def __read_csi_pseudo(self): + def __read_csi_pseudo(self) -> List[list]: """ Create pseudo-CSI list to run the program without CSI/Dynamr. """ @@ -6029,7 +6026,7 @@ def __read_csi_pseudo(self): return sec_str_list - def __write_atom_list(self): + def __write_atom_list(self) -> List[str]: """ Function to create an atom list. """ @@ -6049,7 +6046,7 @@ def __write_atom_list(self): return l_atom_list - def __gap_fill(self, L_list, l_atom): + def __gap_fill(self, L_list: list, l_atom: list) -> List[list]: """ Gap filling function when smooth=0, either i+n or i-n """ @@ -6113,7 +6110,7 @@ def __gap_fill(self, L_list, l_atom): return L_all - def __gap_fill2(self, L_list, l_atom): + def __gap_fill2(self, L_list: list, l_atom: list) -> List[list]: """ Gap filling function when smooth=0, uses averaging of i+n and i-n """ @@ -6186,13 +6183,11 @@ def __gap_fill2(self, L_list, l_atom): return L_all - def __smoothing(self, L_smooth, L_list, l_atom_type): + def __smoothing(self, L_smooth: list, L_list: list, l_atom_type: str) -> List[list]: """ Smoothing function. """ # Building residue number list - first_residue = 0 - last_residue = 0 - first_residue_flag = 0 + first_residue = last_residue = first_residue_flag = 0 smooth_factor = L_smooth[2] central_residue = (smooth_factor // 2) + 1 N_terminus_smooth_factor = central_residue @@ -6301,8 +6296,7 @@ def __smoothing(self, L_smooth, L_list, l_atom_type): while not done: if L_end <= last_residue - offset: # For Ubiquitin L_smooth_list, missing_chemshift = [], [] - bigger_missing = smaller_missing = 0 - new_end = new_start = 0 + bigger_missing = smaller_missing = new_end = new_start = 0 L_residue_number = L_residue_name = L_bmrb_shift = L_simpred_shift = None @@ -6538,7 +6532,10 @@ def __smoothing(self, L_smooth, L_list, l_atom_type): return L_all - def __grid_search(self, l_all_atoms_smooth, smooth_type, lCOp_list, lCAp_list, lCBp_list, lHAp_list, lHp_list, lNp_list, s_final_smooth): + def __grid_search(self, l_all_atoms_smooth: list, smooth_type: str, + lCOp_list: list, lCAp_list: list, lCBp_list: list, lHAp_list: list, + lHp_list: list, lNp_list: list, s_final_smooth: int + ) -> dict: """ Function to do a grid search """ @@ -6942,8 +6939,7 @@ def __grid_search(self, l_all_atoms_smooth, smooth_type, lCOp_list, lCAp_list, l comparison_paramter = entry[0] comparison_method = entry[2] parameter = entry[3] - coefficients = "" - coefficients_for_plot = "" + coefficients = coefficients_for_plot = '' coef_dictionary = entry[4] md_plot_data = entry[5] dynamr_plot_data = entry[6] @@ -6997,7 +6993,7 @@ def __grid_search(self, l_all_atoms_smooth, smooth_type, lCOp_list, lCAp_list, l return ret - def __end_effect(self, l_list): + def __end_effect(self, l_list: list) -> list: """ Function1 to correct sigma for end effects. """ @@ -7049,7 +7045,7 @@ def __end_effect(self, l_list): return result_list - def __end_effect2(self, l_list): + def __end_effect2(self, l_list: list) -> list: """ Function2 to correct sigma for end effects. """ @@ -7101,7 +7097,7 @@ def __end_effect2(self, l_list): return result_list - def __end_effect3(self, l_list): + def __end_effect3(self, l_list: list) -> list: """ Function3 to correct sigma for end effects. """ @@ -7170,7 +7166,7 @@ def __end_effect3(self, l_list): return result_list - def __end_effect4(self, l_list): + def __end_effect4(self, l_list: list) -> list: """ Function4 to correct sigma for end effects. """ @@ -7222,7 +7218,7 @@ def __end_effect4(self, l_list): return result_list - def __end_effect5(self, l_list): + def __end_effect5(self, l_list: list) -> list: """ Function5 to correct sigma for end effects. """ @@ -7270,7 +7266,7 @@ def __end_effect5(self, l_list): return result_list - def __final_smoothing(self, L_smooth, L_list): + def __final_smoothing(self, L_smooth: int, L_list: list) -> List[list]: """ Smoothing function for final result. """ # Building residue number list @@ -7379,8 +7375,7 @@ def __final_smoothing(self, L_smooth, L_list): if L_end <= (last_residue - offset): # For Ubiquitin L_smooth_list, missing_chemshift = [], [] - bigger_missing = smaller_missing = 0 - new_end = new_start = 0 + bigger_missing = smaller_missing = new_end = new_start = 0 L_residue_number = L_residue_name = None # chem_shift_diff_mean = None chem_shift_diff_abs_mean = None @@ -7625,7 +7620,8 @@ def __final_smoothing(self, L_smooth, L_list): return L_all - def __combo(self, l_all_residues, s_best_ten_coef_corr_true, m_coeff_list): + def __combo(self, l_all_residues: list, s_best_ten_coef_corr_true: list, m_coeff_list: list + ) -> Tuple[list, list, float, float]: s_md_result, s_list_of_files = self.__rci_list_build(l_all_residues) ( s_best_ten_coef_corr_true, @@ -7635,7 +7631,7 @@ def __combo(self, l_all_residues, s_best_ten_coef_corr_true, m_coeff_list): ) = self.__rci_only(s_list_of_files, s_md_result, s_best_ten_coef_corr_true, m_coeff_list) return (s_best_ten_coef_corr_true, s_list_of_files, s_Pearson_coeff, s_Spearman_coeff) - def __rci_list_build(self, l_all_residues): + def __rci_list_build(self, l_all_residues: list) -> Tuple[list, list]: """ Function to build a list with chemical shifts for a stand-alone version. """ @@ -7664,7 +7660,9 @@ def __rci_list_build(self, l_all_residues): return (l_md_result, l_list_of_files) - def __rci_only(self, m_list_of_files, m_md_result, m_best_ten_coef_corr_true, l_coeff_list): + def __rci_only(self, m_list_of_files: list, m_md_result: list, + m_best_ten_coef_corr_true: list, l_coeff_list: list + ) -> Tuple[list, list, float, float]: """ Function to create a list of RCI values for further analysis. """ @@ -7690,7 +7688,7 @@ def __rci_only(self, m_list_of_files, m_md_result, m_best_ten_coef_corr_true, l_ dynamr_data.append([residue_number, residue_name, dynamr_value]) dynamr_to_md_ratio = entry_found_true_corr = counter = 0 - corel_coef = l_Pearson_coeff = l_Spearman_coeff = 0 + corel_coef = l_Pearson_coeff = l_Spearman_coeff = 0.0 if len(correlation_true_Dynamr) > 0 and len(correlation_true_MD) > 0: compare_list_corr_true = [abs(corel_coef), filename, "correlation", corel_coef, l_coeff_list, md_data, dynamr_data, dynamr_to_md_ratio] @@ -7718,7 +7716,11 @@ def __rci_only(self, m_list_of_files, m_md_result, m_best_ten_coef_corr_true, l_ return (m_best_ten_coef_corr_true, m_list_of_files, l_Pearson_coeff, l_Spearman_coeff) - def calculate(self, bmrb_to_aa_list, assignment, B_Cys, noshift_res): # pylint: disable=unused-argument,inconsistent-return-statements + def calculate(self, + bmrb_to_aa_list: List[Tuple[str, int]], # [comp_id, seq_id] + assignment: List[Tuple[str, int, str, str, float]], # [comp_id, seq_id, atom_id, atom_type, cs_value] + B_Cys: List[int], # [seq_id] + noshift_res: List[int]) -> dict: # pylint: disable=unused-argument,inconsistent-return-statements """ Calculate Random Coil Index of given assignments """ @@ -7970,20 +7972,12 @@ def calculate(self, bmrb_to_aa_list, assignment, B_Cys, noshift_res): # pylint: preceed_res_cor_NH = self.preceed_res_effect[dyna_simp_res_name_i_minus_1][self.__NH_place][self.__sec_str_place[res_i_csi_sec_str]] preceed_res_cor_HA = self.preceed_res_effect[dyna_simp_res_name_i_minus_1][self.__HA_place][self.__sec_str_place[res_i_csi_sec_str]] else: - preceed_res_cor_N = 0.0 - preceed_res_cor_CO = 0.0 - preceed_res_cor_CA = 0.0 - preceed_res_cor_CB = 0.0 - preceed_res_cor_NH = 0.0 - preceed_res_cor_HA = 0.0 + preceed_res_cor_N = preceed_res_cor_CO = preceed_res_cor_CA =\ + preceed_res_cor_CB = preceed_res_cor_NH = preceed_res_cor_HA = 0.0 if self.preceed_res_effect_flag != 1: - preceed_res_cor_N = 0.0 - preceed_res_cor_CO = 0.0 - preceed_res_cor_CA = 0.0 - preceed_res_cor_CB = 0.0 - preceed_res_cor_NH = 0.0 - preceed_res_cor_HA = 0.0 + preceed_res_cor_N = preceed_res_cor_CO = preceed_res_cor_CA =\ + preceed_res_cor_CB = preceed_res_cor_NH = preceed_res_cor_HA = 0.0 if self.preceed_res_effect_flag == 1 and self.preceed_preceed_res_effect_flag == 1\ and dyna_simp_res_num_i_minus_2 is not None and dyna_simp_res_name_i_minus_2 is not None: @@ -8016,20 +8010,12 @@ def calculate(self, bmrb_to_aa_list, assignment, B_Cys, noshift_res): # pylint: preceed_preceed_res_cor_NH = self.preceed_preceed_res_effect[dyna_simp_res_name_i_minus_2][self.__NH_place][self.__sec_str_place[res_i_csi_sec_str]] preceed_preceed_res_cor_HA = self.preceed_preceed_res_effect[dyna_simp_res_name_i_minus_2][self.__HA_place][self.__sec_str_place[res_i_csi_sec_str]] else: - preceed_preceed_res_cor_N = 0.0 - preceed_preceed_res_cor_CO = 0.0 - preceed_preceed_res_cor_CA = 0.0 - preceed_preceed_res_cor_CB = 0.0 - preceed_preceed_res_cor_NH = 0.0 - preceed_preceed_res_cor_HA = 0.0 + preceed_preceed_res_cor_N = preceed_preceed_res_cor_CO = preceed_preceed_res_cor_CA =\ + preceed_preceed_res_cor_CB = preceed_preceed_res_cor_NH = preceed_preceed_res_cor_HA = 0.0 if self.preceed_preceed_res_effect_flag != 1: - preceed_preceed_res_cor_N = 0.0 - preceed_preceed_res_cor_CO = 0.0 - preceed_preceed_res_cor_CA = 0.0 - preceed_preceed_res_cor_CB = 0.0 - preceed_preceed_res_cor_NH = 0.0 - preceed_preceed_res_cor_HA = 0.0 + preceed_preceed_res_cor_N = preceed_preceed_res_cor_CO = preceed_preceed_res_cor_CA =\ + preceed_preceed_res_cor_CB = preceed_preceed_res_cor_NH = preceed_preceed_res_cor_HA = 0.0 if self.next_res_effect_flag == 1 and dyna_simp_res_num_i_plus_1 is not None and dyna_simp_res_name_i_plus_1 is not None and NoNextProPro != 1: if res_i_csi_sec_str == res_i_plus_1_csi_sec_str and res_num_i_plus_1_sec_str_found == 1 and res_num_i_sec_str_found == 1: @@ -8061,20 +8047,12 @@ def calculate(self, bmrb_to_aa_list, assignment, B_Cys, noshift_res): # pylint: next_res_cor_NH = self.next_res_effect[dyna_simp_res_name_i_plus_1][self.__NH_place][self.__sec_str_place[res_i_csi_sec_str]] next_res_cor_HA = self.next_res_effect[dyna_simp_res_name_i_plus_1][self.__HA_place][self.__sec_str_place[res_i_csi_sec_str]] else: - next_res_cor_N = 0.0 - next_res_cor_CO = 0.0 - next_res_cor_CA = 0.0 - next_res_cor_CB = 0.0 - next_res_cor_NH = 0.0 - next_res_cor_HA = 0.0 + next_res_cor_N = next_res_cor_CO = next_res_cor_CA =\ + next_res_cor_CB = next_res_cor_NH = next_res_cor_HA = 0.0 if self.next_res_effect_flag != 1: - next_res_cor_N = 0.0 - next_res_cor_CO = 0.0 - next_res_cor_CA = 0.0 - next_res_cor_CB = 0.0 - next_res_cor_NH = 0.0 - next_res_cor_HA = 0.0 + next_res_cor_N = next_res_cor_CO = next_res_cor_CA =\ + next_res_cor_CB = next_res_cor_NH = next_res_cor_HA = 0.0 if self.next_res_effect_flag == 1 and self.next_next_res_effect_flag == 1\ and dyna_simp_res_num_i_plus_2 is not None and dyna_simp_res_name_i_plus_2 is not None and NoNextProPro != 1: @@ -8107,20 +8085,12 @@ def calculate(self, bmrb_to_aa_list, assignment, B_Cys, noshift_res): # pylint: next_next_res_cor_NH = self.next_next_res_effect[dyna_simp_res_name_i_plus_2][self.__NH_place][self.__sec_str_place[res_i_csi_sec_str]] next_next_res_cor_HA = self.next_next_res_effect[dyna_simp_res_name_i_plus_2][self.__HA_place][self.__sec_str_place[res_i_csi_sec_str]] else: - next_next_res_cor_N = 0.0 - next_next_res_cor_CO = 0.0 - next_next_res_cor_CA = 0.0 - next_next_res_cor_CB = 0.0 - next_next_res_cor_NH = 0.0 - next_next_res_cor_HA = 0.0 + next_next_res_cor_N = next_next_res_cor_CO = next_next_res_cor_CA =\ + next_next_res_cor_CB = next_next_res_cor_NH = next_next_res_cor_HA = 0.0 if self.next_next_res_effect_flag != 1: - next_next_res_cor_N = 0.0 - next_next_res_cor_CO = 0.0 - next_next_res_cor_CA = 0.0 - next_next_res_cor_CB = 0.0 - next_next_res_cor_NH = 0.0 - next_next_res_cor_HA = 0.0 + next_next_res_cor_N = next_next_res_cor_CO = next_next_res_cor_CA =\ + next_next_res_cor_CB = next_next_res_cor_NH = next_next_res_cor_HA = 0.0 if N_coil_value is not None: final_N = N_coil_value + next_res_cor_N + preceed_res_cor_N + next_next_res_cor_N + preceed_preceed_res_cor_N @@ -8261,3 +8231,5 @@ def calculate(self, bmrb_to_aa_list, assignment, B_Cys, noshift_res): # pylint: self.CAp_list, self.CBp_list, self.HAp_list, self.Hp_list, self.Np_list, self.final_smooth) + + return {}