#include "Executive.h" #include "ExecutivePython.h" #ifndef _PYMOL_NOPY #include "ObjectAlignment.h" #include "ObjectCGO.h" #include "ObjectCallback.h" #include "ObjectMap.h" #include "P.h" #include "Feedback.h" pymol::Result<> ExecutiveLoadObject(PyMOLGlobals* G, const char* oname, PyObject* model, int frame, int type, int finish, int discrete, int quiet, int zoom) { ObjectNameType valid_name = ""; pymol::CObject *origObj = nullptr, *obj; OrthoLineType buf; buf[0] = 0; ExecutiveProcessObjectName(G, oname, valid_name); origObj = ExecutiveFindObjectByName(G, valid_name); /* TODO check for existing object of wrong type */ switch (type) { case cLoadTypeChemPyModel: { if (origObj) { if (origObj->type != cObjectMolecule) { ExecutiveDelete(G, valid_name); origObj = nullptr; } } PBlock(G); /*PBlockAndUnlockAPI(); */ obj = ObjectMoleculeLoadChemPyModel( G, (ObjectMolecule*) origObj, model, frame, discrete); PUnblock(G); /*PLockAPIAndUnblock(); */ if (!origObj) { if (obj) { ObjectSetName(obj, valid_name); ExecutiveManageObject(G, obj, zoom, quiet); if (frame < 0) frame = ((ObjectMolecule*) obj)->NCSet - 1; sprintf(buf, " CmdLoad: ChemPy-model loaded into object \"%s\", state %d.\n", valid_name, frame + 1); } } else if (origObj) { if (finish) ExecutiveUpdateObjectSelection(G, origObj); if (frame < 0) frame = ((ObjectMolecule*) origObj)->NCSet - 1; sprintf(buf, " CmdLoad: ChemPy-model appended into object \"%s\", state %d.\n", valid_name, frame + 1); } break; } case cLoadTypeChemPyBrick: if (origObj) if (origObj->type != cObjectMap) { ExecutiveDelete(G, valid_name); origObj = nullptr; } PBlock(G); /*PBlockAndUnlockAPI(); */ obj = ObjectMapLoadChemPyBrick( G, (ObjectMap*) origObj, model, frame, discrete, quiet); PUnblock(G); /*PLockAPIAndUnblock(); */ if (!origObj) { if (obj) { ObjectSetName(obj, valid_name); ExecutiveManageObject(G, obj, zoom, quiet); sprintf(buf, " CmdLoad: chempy.brick loaded into object \"%s\"\n", valid_name); } } else if (origObj) { sprintf(buf, " CmdLoad: chempy.brick appended into object \"%s\"\n", valid_name); } break; case cLoadTypeChemPyMap: if (origObj) if (origObj->type != cObjectMap) { ExecutiveDelete(G, valid_name); origObj = nullptr; } PBlock(G); /*PBlockAndUnlockAPI(); */ obj = ObjectMapLoadChemPyMap( G, (ObjectMap*) origObj, model, frame, discrete, quiet); PUnblock(G); /*PLockAPIAndUnblock(); */ if (!origObj) { if (obj) { ObjectSetName(obj, valid_name); ExecutiveManageObject(G, obj, zoom, quiet); sprintf(buf, " CmdLoad: chempy.map loaded into object \"%s\"\n", valid_name); } } else if (origObj) { sprintf(buf, " CmdLoad: chempy.map appended into object \"%s\"\n", valid_name); } break; case cLoadTypeCallback: if (origObj) if (origObj->type != cObjectCallback) { ExecutiveDelete(G, valid_name); origObj = nullptr; } PBlock(G); /*PBlockAndUnlockAPI(); */ obj = ObjectCallbackDefine( G, (ObjectCallback*) origObj, model, frame); PUnblock(G); /*PLockAPIAndUnblock(); */ if (!origObj) { if (obj) { ObjectSetName(obj, valid_name); ExecutiveManageObject(G, obj, zoom, quiet); sprintf(buf, " CmdLoad: pymol.callback loaded into object \"%s\"\n", valid_name); } } else if (origObj) { sprintf(buf, " CmdLoad: pymol.callback appended into object \"%s\"\n", valid_name); } break; case cLoadTypeCGO: if (origObj) if (origObj->type != cObjectCGO) { ExecutiveDelete(G, valid_name); origObj = nullptr; } PBlock(G); /*PBlockAndUnlockAPI(); */ obj = ObjectCGODefine(G, (ObjectCGO*) origObj, model, frame); PUnblock(G); /*PLockAPIAndUnblock(); */ if (!origObj) { if (obj) { ObjectSetName(obj, valid_name); ExecutiveManageObject(G, obj, zoom, quiet); sprintf(buf, " CmdLoad: CGO loaded into object \"%s\"\n", valid_name); } } else if (origObj) { sprintf(buf, " CmdLoad: CGO appended into object \"%s\"\n", valid_name); } break; } if (origObj && !quiet) { PRINTFB(G, FB_Executive, FB_Actions) "%s", buf ENDFB(G); OrthoRestorePrompt(G); } return {}; } pymol::Result<> ExecutiveSetRawAlignment(PyMOLGlobals* G, pymol::zstring_view alnname, PyObject* raw, pymol::zstring_view guidename, int state, int quiet) { ObjectMolecule* guide = nullptr; if (!guidename.empty()) { guide = ExecutiveFindObject(G, guidename.c_str()); } if(!PyList_Check(raw)) { return pymol::make_error("alignment must be list"); } auto n_cols = PyList_Size(raw); pymol::vla align_vla(n_cols * 3); size_t vla_offset = 0; for(size_t c = 0; c < n_cols; ++c) { PyObject * col = PyList_GetItem(raw, c); if(!PyList_Check(col)) { return pymol::make_error("columns must be list"); } auto n_idx = PyList_Size(col); for(size_t i = 0; i < n_idx; ++i) { const char * model; int index; PyObject * idx = PyList_GetItem(col, i); if(!PyArg_ParseTuple(idx, "si", &model, &index)) { return pymol::make_error("indices must be (str, int)"); } auto mol = ExecutiveFindObject(G, model); if(!mol) { return pymol::make_error("object ", model, " not found"); } if (!guide) { guide = mol; } if (index < 1 || mol->NAtom < index) { return pymol::make_error("index ('", model, ", ", index, ") out of range"); } auto uid = AtomInfoCheckUniqueID(G, mol->AtomInfo + index - 1); *(align_vla.check(vla_offset++)) = uid; } *(align_vla.check(vla_offset++)) = 0; } align_vla.resize(vla_offset); // does alignment object already exist? auto cobj = ExecutiveFindObjectByName(G, alnname.c_str()); if (cobj && cobj->type != cObjectAlignment) { ExecutiveDelete(G, cobj->Name); cobj = nullptr; } // create alignment object cobj = ObjectAlignmentDefine(G, (ObjectAlignment*) cobj, align_vla, state, true, guide, nullptr); // manage alignment object ObjectSetName(cobj, alnname.c_str()); ExecutiveManageObject(G, cobj, 0, quiet); SceneInvalidate(G); // make available as selection FIXME find better solution cobj->update(); return {}; } pymol::Result ExecutiveFitPairs( PyMOLGlobals* G, PyObject* list, int quiet) { auto ln = PyObject_Length(list); if (!ln) { return pymol::make_error("No selections provided"); } if (ln & 0x1) { return pymol::make_error( G, "FitPairs", "must supply an even number of selections."); } std::vector word(ln); int a = 0; while (a < ln) { unique_PyObject_ptr item(PySequence_GetItem(list, a)); auto tmp = SelectorTmp::make(G, PyString_AsString(item.get())); p_return_if_error(tmp); word[a] = std::move(tmp.result()); a++; } return ExecutiveRMSPairs(G, word, 2, quiet); } /** * Implementation of ExecutiveGetRawAlignment * @param alnobj alignment object * @param active_only only consider active alignments * @param state state of alignment object * @return a list of lists of (object, index) tuples containing the * raw per-atom alignment relationships */ static pymol::Result ExecutiveGetRawAlignmentImpl( PyMOLGlobals* G, const ObjectAlignment* alnobj, bool active_only, int state) { if (state >= alnobj->getNFrame()) { return pymol::make_error( "Index Error: state ", state, " >= NState ", alnobj->getNFrame()); } const auto& vla = alnobj->State[state].alignVLA; if (!vla) { return pymol::make_error("state ", state, " not valid"); } auto hide_underscore = SettingGet(G, cSetting_hide_underscore_names); const auto vla_len = VLAGetSize(vla); PyObject* raw = PyList_New(0); for (size_t i = 0; i < vla_len; ++i) { PyObject* col = PyList_New(0); for (int id; (id = vla[i]); ++i) { auto eoo = ExecutiveUniqueIDAtomDictGet(G, id); if (eoo && (!active_only || eoo->obj->Enabled) && (!hide_underscore || eoo->obj->Name[0] != '_')) { PyObject* idx = Py_BuildValue("si", eoo->obj->Name, eoo->atm + 1); PyList_Append(col, idx); Py_DECREF(idx); } } if (PyList_Size(col) > 0) { PyList_Append(raw, col); } Py_DECREF(col); } return raw; } pymol::Result ExecutiveGetRawAlignment(PyMOLGlobals* G, pymol::null_safe_zstring_view name, bool active_only, int state) { if (name.empty()) { name = ExecutiveGetActiveAlignment(G); } if (!name.empty()) { if (auto obj = ExecutiveFindObject(G, name)) { return ExecutiveGetRawAlignmentImpl(G, obj, active_only, state); } } return pymol::make_error("No such alignment: ", name); } #endif