Source code for ccpn.core.lib.Util

"""CCPN-level utility code independent of model content

"""
#=========================================================================================
# Licence, Reference and Credits
#=========================================================================================
__copyright__ = "Copyright (C) CCPN project (http://www.ccpn.ac.uk) 2014 - 2021"
__credits__ = ("Ed Brooksbank, Luca Mureddu, Timothy J Ragan & Geerten W Vuister")
__licence__ = ("CCPN licence. See http://www.ccpn.ac.uk/v3-software/downloads/license")
__reference__ = ("Skinner, S.P., Fogh, R.H., Boucher, W., Ragan, T.J., Mureddu, L.G., & Vuister, G.W.",
                 "CcpNmr AnalysisAssign: a flexible platform for integrated NMR analysis",
                 "J.Biomol.Nmr (2016), 66, 111-124, http://doi.org/10.1007/s10858-016-0060-y")
#=========================================================================================
# Last code modification
#=========================================================================================
__modifiedBy__ = "$modifiedBy: Ed Brooksbank $"
__dateModified__ = "$dateModified: 2021-02-04 12:07:30 +0000 (Thu, February 04, 2021) $"
__version__ = "$Revision: 3.0.3 $"
#=========================================================================================
# Created
#=========================================================================================
__author__ = "$Author: CCPN $"
__date__ = "$Date: 2017-04-07 10:28:41 +0000 (Fri, April 07, 2017) $"
#=========================================================================================
# Start of code
#=========================================================================================

import collections
import inspect
from typing import Optional
from ccpn.core.lib import Pid
from ccpn.core import _coreClassMap


[docs]def pid2PluralName(pid: str) -> str: """Get plural class name, (e.g. 'peaks', 'spectra' from short-form or long-form, Pid string Unrecognised strings are returned unchanged""" from ccpn.core.Project import Project tag = pid.split(Pid.PREFIXSEP, 1)[0] cls = Project._className2Class.get(tag) if cls is None: return tag else: return cls._pluralLinkName
[docs]def getParentPid(childPid) -> Pid.Pid: """Get the pid of parent of childPid; only uses Pid definitions (i.e. does not involve the actual objects) :returns Pid instance defining parent """ if not isinstance(childPid, (str, Pid.Pid)): raise ValueError('Invalid pid "%s"' % childPid) childPid = Pid.Pid(childPid) if childPid.type not in _coreClassMap: raise ValueError('Invalid pid "%s"' % childPid) klass = _coreClassMap[childPid.type] parentClass = klass._parentClass offset = klass._numberOfIdFields fields = [parentClass.shortClassName] + list(childPid.fields[:-offset]) parentPid = Pid.Pid.new(*fields) return parentPid
[docs]def getParentObjectFromPid(project, pid): """Get a parent object from a pid, which may represent a deleted object. :returns: Parent object or None on error/non-existence Example: pid = 'NA:A.40.ALA.CB' getParentObjectFromPid(pid) -> 'NR:A.40.ALA' """ if not isinstance(pid, (str, Pid.Pid)): raise ValueError('Invalid pid "%s"' % pid) obj = None # First try if the object defined by pid still exists try: obj = project.getByPid(pid) if obj is not None: return obj._parent except: pass if obj is None: parentPid = getParentPid(pid) obj = project.getByPid(parentPid) return obj
# Atom ID AtomIdTuple = collections.namedtuple('AtomIdTuple', ['chainCode', 'sequenceCode', 'residueType', 'atomName', ])
[docs]def commandParameterString(*params, values: dict = None, defaults: dict = None): """Make parameter string to insert into function call string. params are positional parameters in order, values are keyword parameters. If the defaults dictionary is passed in, only parameters in defaults are added to the string, and only if the value differs from the default. This allows you to pass in values=locals(). The order of keyword parameters follows defaults if given, else values, so you can get ordered parameters by passing in ordered dictionaries. Wrapper object values are replaced with their Pids Example: commandParameterString(11, values={a:1, b:<Note NO:notename>, c:2, d:3, e:4}, defaults=OrderedDict(d=8, b=None, c=2)) will return "11, d=3, b='NO:notename'" """ from ccpn.core._implementation.AbstractWrapperObject import AbstractWrapperObject ll = [] for val in params: if isinstance(val, AbstractWrapperObject): val = val.pid ll.append(repr(val)) if values: if defaults: for tag, default in defaults.items(): val = values[tag] if val != default: if isinstance(val, AbstractWrapperObject): val = val.pid ll.append('%s=%s' % (tag, repr(val))) else: for tag, val in values.items(): if isinstance(val, AbstractWrapperObject): val = val.pid ll.append('%s=%s' % (tag, repr(val))) # return ', '.join(ll)
[docs]def commandParameterStringValues(*params, values: dict = None, defaults: dict = None): """Make parameter string to insert into function call string. params are positional parameters in order, values are keyword parameters. If the defaults dictionary is passed in, only parameters in defaults are added to the string, and only if the value differs from the default. This allows you to pass in values=locals(). The order of keyword parameters follows defaults if given, else values, so you can get ordered parameters by passing in ordered dictionaries. Wrapper object values are replaced with their Pids Example: commandParameterString(11, values={a:1, b:<Note NO:notename>, c:2, d:3, e:4}, defaults=OrderedDict(d=8, b=None, c=2)) will return "11, d=3, b='NO:notename'" """ from ccpn.core._implementation.AbstractWrapperObject import AbstractWrapperObject ll = [] for val in params: if isinstance(val, AbstractWrapperObject): val = val.pid ll.append(repr(val)) if values: if defaults: for tag, default in defaults.items(): val = values[tag] if val != default: if isinstance(val, AbstractWrapperObject): val = val.pid ll.append('%s=%s' % (tag, repr(val))) else: for tag, val in values.items(): if isinstance(val, AbstractWrapperObject): val = val.pid ll.append('%s=%s' % (tag, repr(val))) # return ', '.join(ll)
[docs]def funcCaller() -> Optional[str]: """ return the name of the current function (actually the parent caller to this function, hence the index of '1') :return: string name """ try: return inspect.stack()[1][3] except: return None