From 9f0d3a23b54af8a2504b0f409cfa6ee605ca7f62 Mon Sep 17 00:00:00 2001 From: Ezra Peisach Date: Tue, 23 Jan 2024 11:30:42 -0500 Subject: [PATCH] added _getCovalentBondContentOp() and _updateCovalentBondContentOp() --- wwpdb/apps/ann_tasks_v2/__init__.py | 2 +- .../ann_tasks_v2/utils/GetCloseContact.py | 13 +- .../ann_tasks_v2/utils/GetCovalentBond.py | 166 ++++++++++++++++++ .../ann_tasks_v2/utils/UpdateCloseContact.py | 4 +- .../ann_tasks_v2/utils/UpdateCovalentBond.py | 95 ++++++++++ .../webapp/AnnTasksWebAppWorker.py | 63 +++++++ 6 files changed, 334 insertions(+), 9 deletions(-) create mode 100644 wwpdb/apps/ann_tasks_v2/utils/GetCovalentBond.py create mode 100644 wwpdb/apps/ann_tasks_v2/utils/UpdateCovalentBond.py diff --git a/wwpdb/apps/ann_tasks_v2/__init__.py b/wwpdb/apps/ann_tasks_v2/__init__.py index 1d39bd0..6daa821 100644 --- a/wwpdb/apps/ann_tasks_v2/__init__.py +++ b/wwpdb/apps/ann_tasks_v2/__init__.py @@ -2,4 +2,4 @@ __author__ = "Ezra Peisach" __email__ = "ezra.peisach@rcsb.org" __license__ = "Apache 2.0" -__version__ = "0.36" +__version__ = "0.37" diff --git a/wwpdb/apps/ann_tasks_v2/utils/GetCloseContact.py b/wwpdb/apps/ann_tasks_v2/utils/GetCloseContact.py index 2e84c96..3d49293 100644 --- a/wwpdb/apps/ann_tasks_v2/utils/GetCloseContact.py +++ b/wwpdb/apps/ann_tasks_v2/utils/GetCloseContact.py @@ -5,7 +5,7 @@ # Update: ## """ -Manage utility to correct TLS problems +Manage utility to correct close contact problems """ __docformat__ = "restructuredtext en" @@ -45,7 +45,7 @@ def run(self, entryId, inpFile): retD["found"] = "no" try: inpPath = os.path.join(self.__sessionPath, inpFile) - logPath = os.path.join(self.__sessionPath, entryId + "-close-contact.log") + logPath = os.path.join(self.__sessionPath, entryId + "-get-close-contact.log") retPath = os.path.join(self.__sessionPath, entryId + "-close-contact.json") for filePath in (logPath, retPath): if os.access(filePath, os.R_OK): @@ -85,10 +85,11 @@ def __processCloseContactContent(self, jsonObj): + onClick="select_close_contact_covalent_bond('update-close-contact-form', 'close_contact_', 'close_contact_select_all', '');" /> %s - +

@@ -149,8 +150,8 @@ def __processCloseContactContent(self, jsonObj): select_green_button = "" if (green_count > 0) and (green_count < len(jsonObj["close_contact"])): select_green_button = ( - '" + '" ) # return htmlTemplate % (str(count), select_green_button, tablerow) diff --git a/wwpdb/apps/ann_tasks_v2/utils/GetCovalentBond.py b/wwpdb/apps/ann_tasks_v2/utils/GetCovalentBond.py new file mode 100644 index 0000000..88585cc --- /dev/null +++ b/wwpdb/apps/ann_tasks_v2/utils/GetCovalentBond.py @@ -0,0 +1,166 @@ +## +# File: GetCovalentBond.py +# Date: 28-Sep-2020 Zukang Feng +# +# Update: +## +""" +Manage utility to correct covalent bond problems + +""" +__docformat__ = "restructuredtext en" +__author__ = "Zukang Feng" +__email__ = "zfeng@rcsb.rutgers.edu" +__license__ = "Creative Commons Attribution 3.0 Unported" +__version__ = "V0.07" + +import json +import os +import sys +import traceback + +from wwpdb.utils.dp.RcsbDpUtility import RcsbDpUtility + + +class GetCovalentBond(object): + """ + GetCovalentBond class encapsulates correcting covalent bond problems. + """ + + def __init__(self, reqObj=None, verbose=False, log=sys.stderr): + self.__reqObj = reqObj + self.__verbose = verbose + self.__lfh = log + # + self.__setup() + + def __setup(self): + self.__siteId = self.__reqObj.getValue("WWPDB_SITE_ID") + self.__sObj = self.__reqObj.getSessionObj() + self.__sessionPath = self.__sObj.getPath() + + def run(self, entryId, inpFile): + """Run the calculation""" + retD = {} + retD["found"] = "no" + try: + inpPath = os.path.join(self.__sessionPath, inpFile) + logPath = os.path.join(self.__sessionPath, entryId + "-get-covalent-bond.log") + retPath = os.path.join(self.__sessionPath, entryId + "-covalent-bond.json") + for filePath in (logPath, retPath): + if os.access(filePath, os.R_OK): + os.remove(filePath) + # + # + dp = RcsbDpUtility(tmpPath=self.__sessionPath, siteId=self.__siteId, verbose=self.__verbose, log=self.__lfh) + # + dp.imp(inpPath) + dp.op("annot-get-covalent-bond") + dp.expLog(dstPath=logPath, appendMode=False) + dp.exp(retPath) + # + if os.access(retPath, os.R_OK): + with open(retPath) as ifh: + jsonObj = json.load(ifh) + htmlcontent = self.__processCloseContactContent(jsonObj) + if htmlcontent: + retD["htmlcontent"] = htmlcontent + retD["found"] = "yes" + # + # + # + dp.cleanup() + except: # noqa: E722 pylint: disable=bare-except + traceback.print_exc(file=self.__lfh) + # + return retD + + def __processCloseContactContent(self, jsonObj): + """ """ + if (not jsonObj) or ("covalent_bond" not in jsonObj) or (not jsonObj["covalent_bond"]): + return "" + # + htmlTemplate = """ + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + %s +
Atom1Atom2Distance
Chain IDResidueNumberAtomSymmetryChain IDResidueNumberAtomSymmetry
+ """ + # + tablerow = "" + count = 0 + for tupL in jsonObj["covalent_bond"]: + tablerow += "" + # + atom = tupL[4] + if tupL[5]: + atom += "(" + tupL[5] + ")" + # + tablerow += "" + tupL[0] + "" + "" + tupL[1] + "" + "" + tupL[2] + tupL[3] + "" + "" + atom + "" + "" + tupL[6] + "" + atom = tupL[11] + if tupL[12]: + atom += "(" + tupL[12] + ")" + # + tablerow += "" + tupL[7] + "" + "" + tupL[8] + "" + "" + tupL[9] + tupL[10] + "" + "" + atom + "" + "" + tupL[13] + "" + # + tupL[6] = tupL[6].replace("_", "-"); + tupL[13] = tupL[13].replace("_", "-"); + bond_id = "covalent_bond_" + str(count) + # + tablerow += "" + tupL[14] + '        ' + # + tablerow += "\n" + count += 1 + # + return htmlTemplate % (str(count), tablerow) + + +def main(): + from wwpdb.utils.config.ConfigInfo import ConfigInfo + from wwpdb.utils.session.WebRequest import InputRequest + + # + siteId = os.getenv("WWPDB_SITE_ID") + cI = ConfigInfo(siteId) + # + myReqObj = InputRequest({}, verbose=True, log=sys.stderr) + myReqObj.setValue("TopSessionPath", cI.get("SITE_WEB_APPS_TOP_SESSIONS_PATH")) + myReqObj.setValue("TopPath", cI.get("SITE_WEB_APPS_TOP_PATH")) + myReqObj.setValue("WWPDB_SITE_ID", siteId) + myReqObj.setValue("sessionid", "d581f7aa63cc8feba7d96fb9fd103866fca45a7d") + # + calc = GetCovalentBond(reqObj=myReqObj, verbose=True, log=sys.stderr) + retD = calc.run("D_1000001900", "D_1000001900_model_P1.cif") + for k, v in retD.items(): + print(k + "=" + v) + + +if __name__ == "__main__": + main() diff --git a/wwpdb/apps/ann_tasks_v2/utils/UpdateCloseContact.py b/wwpdb/apps/ann_tasks_v2/utils/UpdateCloseContact.py index c4df8bc..a6b8fe8 100644 --- a/wwpdb/apps/ann_tasks_v2/utils/UpdateCloseContact.py +++ b/wwpdb/apps/ann_tasks_v2/utils/UpdateCloseContact.py @@ -5,7 +5,7 @@ # Update: ## """ -Manage utility to correct TLS problems +Manage utility to correct close contact problems """ __docformat__ = "restructuredtext en" @@ -59,7 +59,7 @@ def run(self, entryId, inpFile, closeContactList): """Run the calculation""" try: inpPath = os.path.join(self.__sessionPath, inpFile) - logPath = os.path.join(self.__sessionPath, entryId + "-close-contact.log") + logPath = os.path.join(self.__sessionPath, entryId + "-update-close-contact.log") dataPath = os.path.join(self.__sessionPath, entryId + "-close-contact.txt") for filePath in (logPath, dataPath): if os.access(filePath, os.R_OK): diff --git a/wwpdb/apps/ann_tasks_v2/utils/UpdateCovalentBond.py b/wwpdb/apps/ann_tasks_v2/utils/UpdateCovalentBond.py new file mode 100644 index 0000000..cd4ab69 --- /dev/null +++ b/wwpdb/apps/ann_tasks_v2/utils/UpdateCovalentBond.py @@ -0,0 +1,95 @@ +## +# File: UpdateCovalentBond.py +# Date: 22-Jan-2024 Zukang Feng +# +# Update: +## +""" +Manage utility to correct covalent bond problems + +""" +__docformat__ = "restructuredtext en" +__author__ = "Zukang Feng" +__email__ = "zfeng@rcsb.rutgers.edu" +__license__ = "Creative Commons Attribution 3.0 Unported" +__version__ = "V0.07" + +import sys +import os.path +import os +import traceback + +from wwpdb.utils.dp.RcsbDpUtility import RcsbDpUtility +from wwpdb.apps.ann_tasks_v2.utils.SessionWebDownloadUtils import SessionWebDownloadUtils + + +class UpdateCovalentBond(SessionWebDownloadUtils): + """ + UpdateCovalentBond class encapsulates correcting covalent bond problems. + + """ + + def __init__(self, reqObj=None, verbose=False, log=sys.stderr): + super(UpdateCovalentBond, self).__init__(reqObj=reqObj, verbose=verbose, log=log) + self.__verbose = verbose + self.__lfh = log + self.__reqObj = reqObj + # + self.__setup() + + def __setup(self): + self.__siteId = self.__reqObj.getValue("WWPDB_SITE_ID") + self.__sObj = self.__reqObj.getSessionObj() + self.__sessionPath = self.__sObj.getPath() + + def __checkStatus(self, logFilePath): + status = "error" + if os.access(logFilePath, os.R_OK): + ifh = open(logFilePath, "r") + for line in ifh: + if str(line).startswith("Finished!"): + status = "ok" + break + # + # + # + return status + + def run(self, entryId, inpFile, closeContactList): + """Run the calculation""" + try: + inpPath = os.path.join(self.__sessionPath, inpFile) + logPath = os.path.join(self.__sessionPath, entryId + "-update-covalent-bond.log") + dataPath = os.path.join(self.__sessionPath, entryId + "-covalent-bond.txt") + for filePath in (logPath, dataPath): + if os.access(filePath, os.R_OK): + os.remove(filePath) + # + # + ofh = open(dataPath, "w") + for closeContact in closeContactList: + ofh.write("%s\n" % closeContact) + # + ofh.close() + # + status = False + dp = RcsbDpUtility(tmpPath=self.__sessionPath, siteId=self.__siteId, verbose=self.__verbose, log=self.__lfh) + # + dp.imp(inpPath) + dp.addInput(name="datafile", value=dataPath) + dp.op("annot-remove-covalent-bond") + dp.expLog(dstPath=logPath, appendMode=False) + if os.access(logPath, os.R_OK): + self.addDownloadPath(logPath) + if self.__checkStatus(logPath) == "ok": + dp.exp(inpPath) + self.addDownloadPath(inpPath) + status = True + # + # + dp.cleanup() + return status + except: # noqa: E722 pylint: disable=bare-except + traceback.print_exc(file=self.__lfh) + return False + # diff --git a/wwpdb/apps/ann_tasks_v2/webapp/AnnTasksWebAppWorker.py b/wwpdb/apps/ann_tasks_v2/webapp/AnnTasksWebAppWorker.py index 8bcc233..2733154 100644 --- a/wwpdb/apps/ann_tasks_v2/webapp/AnnTasksWebAppWorker.py +++ b/wwpdb/apps/ann_tasks_v2/webapp/AnnTasksWebAppWorker.py @@ -9,6 +9,8 @@ # 13-Jan-2017 ep add support for correcting occupancy on special position # 02-Oct-2017 zf add /service/ann_tasks_v2/entityloadinfo, /service/ann_tasks_v2/symoploadinfo # 14-Jun-2019 zf add automatical filling in assembly for NMR entry +# 28-Sep-2020 zf add _getCloseContactContentOp() and _updateCloseContactContentOp() +# 22-Jan-2024 zf add _getCovalentBondContentOp() and _updateCovalentBondContentOp() # ## """ @@ -42,11 +44,13 @@ from wwpdb.apps.ann_tasks_v2.expIoUtils.ReSetFreeRinSFmmCIF import ReSetFreeRinSFmmCIF from wwpdb.apps.ann_tasks_v2.related.Related import Related from wwpdb.apps.ann_tasks_v2.utils.GetCloseContact import GetCloseContact +from wwpdb.apps.ann_tasks_v2.utils.GetCovalentBond import GetCovalentBond from wwpdb.apps.ann_tasks_v2.utils.PdbFile import PdbFile from wwpdb.apps.ann_tasks_v2.utils.PublicPdbxFile import PublicPdbxFile from wwpdb.apps.ann_tasks_v2.utils.TaskSessionState import TaskSessionState from wwpdb.apps.ann_tasks_v2.utils.TlsRange import TlsRange from wwpdb.apps.ann_tasks_v2.utils.UpdateCloseContact import UpdateCloseContact +from wwpdb.apps.ann_tasks_v2.utils.UpdateCovalentBond import UpdateCovalentBond from wwpdb.utils.session.WebRequest import ResponseContent from wwpdb.io.file.DataExchange import DataExchange @@ -149,6 +153,8 @@ def __init__(self, reqObj=None, verbose=False, log=sys.stderr): "/service/ann_tasks_v2/edit_em_map_header_responder": "_editEmMapHeaderResponderOp", "/service/ann_tasks_v2/get_close_contact_content": "_getCloseContactContentOp", "/service/ann_tasks_v2/update_close_contact_content": "_updateCloseContactContentOp", + "/service/ann_tasks_v2/get_covalent_bond_content": "_getCovalentBondContentOp", + "/service/ann_tasks_v2/update_covalent_bond_content": "_updateCovalentBondContentOp", "placeholder": "_dumpOp", } self.addServices(self.__appPathD) @@ -776,6 +782,63 @@ def _updateCloseContactContentOp(self): return rC + def _getCovalentBondContentOp(self): + """Read covalent bond information from coordinate model file""" + if self._verbose: + self._lfh.write("+AnnTasksWebAppWorker._getCovalentBondContentOp() starting\n") + # + self._getSession(useContext=True) + fileName = self._reqObj.getValue("entryfilename") + entryId = self._reqObj.getValue("entryid") + # + calc = GetCovalentBond(reqObj=self._reqObj, verbose=self._verbose, log=self._lfh) + retD = calc.run(entryId, fileName) + + rC = ResponseContent(reqObj=self._reqObj, verbose=self._verbose, log=self._lfh) + rC.setReturnFormat("json") + rC.addDictionaryItems(cD=retD) + + return rC + + def _updateCovalentBondContentOp(self): + """Remove selected covalent bond(s) in coordinate model file""" + if self._verbose: + self._lfh.write("+AnnTasksWebAppWorker._updateCovalentBondContentOp() starting\n") + # + self._getSession(useContext=True) + fileName = self._reqObj.getValue("entryfilename") + entryId = self._reqObj.getValue("entryid") + covalent_bond_list = [] + covalent_bond_num_str = self._reqObj.getValue("total_covalent_bond_num") + if covalent_bond_num_str: + covalent_bond_num = int(covalent_bond_num_str) + for i in range(0, covalent_bond_num): + covalent_bond = self._reqObj.getValue("covalent_bond_" + str(i)) + if covalent_bond: + covalent_bond_list.append(covalent_bond) + # + # + # + if not covalent_bond_list: + rC = ResponseContent(reqObj=self._reqObj, verbose=self._verbose, log=self._lfh) + rC.setReturnFormat("json") + rC.setError(errMsg="No record selected") + return rC + # + calc = UpdateCovalentBond(reqObj=self._reqObj, verbose=self._verbose, log=self._lfh) + ok = calc.run(entryId, fileName, covalent_bond_list) + + if self._verbose: + self._lfh.write("+AnnTasksWebAppWorker._updateCovalentBondContentOp() status %r\n" % ok) + + tagL = calc.getAnchorTagList(label=None, target="_blank", cssClass="") + # + tss = TaskSessionState(reqObj=self._reqObj, verbose=self._verbose, log=self._lfh) + tss.assign(name="Remove covalent bond(s)", formId="#review-covalent-bond-form", args="", completionFlag=ok, tagList=tagL, entryId=entryId, entryFileName=fileName) + rC = self._makeTaskResponse(tssObj=tss) + + return rC + def __checkAssemblyInfo(self, modelFile): """Check if model file already has assembly information""" if not os.access(modelFile, os.F_OK):