static PyObject *contacts(PyObject *self, PyObject *args) { int mol1, frame1, mol2, frame2; PyObject *selected1, *selected2; float cutoff; if (!PyArg_ParseTuple(args, (char *)"iiO!iiO!f:atomselection.contacts", &mol1, &frame1, &PyTuple_Type, &selected1, &mol2, &frame2, &PyTuple_Type, &selected2, &cutoff)) return NULL; VMDApp *app = get_vmdapp(); AtomSel *sel1 = sel_from_py(mol1, frame1, selected1, app); AtomSel *sel2 = sel_from_py(mol2, frame2, selected2, app); if (!sel1 || !sel2) { delete sel1; delete sel2; return NULL; } const float *ts1 = sel1->coordinates(app->moleculeList); const float *ts2 = sel2->coordinates(app->moleculeList); if (!ts1 || !ts2) { PyErr_SetString(PyExc_ValueError, "No coordinates in selection"); delete sel1; delete sel2; return NULL; } Molecule *mol = app->moleculeList->mol_from_id(mol1); GridSearchPair *pairlist = vmd_gridsearch3( ts1, sel1->num_atoms, sel1->on, ts2, sel2->num_atoms, sel2->on, cutoff, -1, (sel1->num_atoms + sel2->num_atoms) * 27); delete sel1; delete sel2; GridSearchPair *p, *tmp; PyObject *list1 = PyList_New(0); PyObject *list2 = PyList_New(0); for (p=pairlist; p != NULL; p=tmp) { // throw out pairs that are already bonded MolAtom *a1 = mol->atom(p->ind1); if (mol1 != mol2 || !a1->bonded(p->ind2)) { PyList_Append(list1, PyInt_FromLong(p->ind1)); PyList_Append(list2, PyInt_FromLong(p->ind2)); } tmp = p->next; free(p); } PyObject *result = PyList_New(2); PyList_SET_ITEM(result, 0, list1); PyList_SET_ITEM(result, 1, list2); return result; }
static PyObject *center(PyObject *self, PyObject *args) { int molid, frame; PyObject *selected; PyObject *weightobj = NULL; AtomSel *sel; // parse arguments if (!PyArg_ParseTuple(args, (char *)"iiO!|O", &molid, &frame, &PyTuple_Type, &selected, &weightobj)) return NULL; VMDApp *app = get_vmdapp(); // get selection if (!(sel = sel_from_py(molid, frame, selected, app))) return NULL; // get weight float *weight = parse_weight(sel, weightobj); if (!weight) return NULL; float cen[3]; // compute center int ret_val = measure_center(sel, sel->coordinates(app->moleculeList), weight, cen); delete [] weight; delete sel; if (ret_val < 0) { PyErr_SetString(PyExc_ValueError, measure_error(ret_val)); return NULL; } // return as (x, y, z) PyObject *cenobj = PyTuple_New(3); for (int i=0; i<3; i++) PyTuple_SET_ITEM(cenobj, i, PyFloat_FromDouble(cen[i])); return cenobj; }
static PyObject *py_rmsd(PyObject *self, PyObject *args) { int mol1, frame1, mol2, frame2; PyObject *selected1, *selected2, *weightobj = NULL; if (!PyArg_ParseTuple(args, (char *)"iiO!iiO!O:atomselection.rmsd", &mol1, &frame1, &PyTuple_Type, &selected1, &mol2, &frame2, &PyTuple_Type, &selected2, &weightobj)) return NULL; VMDApp *app = get_vmdapp(); AtomSel *sel1 = sel_from_py(mol1, frame1, selected1, app); AtomSel *sel2 = sel_from_py(mol2, frame2, selected2, app); if (!sel1 || !sel2) { delete sel1; delete sel2; return NULL; } const Timestep *ts1 =app->moleculeList->mol_from_id(mol1)->get_frame(frame1); const Timestep *ts2 =app->moleculeList->mol_from_id(mol2)->get_frame(frame2); if (!ts1 || !ts2) { PyErr_SetString(PyExc_ValueError, "No coordinates in selection"); delete sel1; delete sel2; return NULL; } float *weight = parse_weight(sel1, weightobj); if (!weight) { delete sel1; delete sel2; return NULL; } float rmsd; int rc = measure_rmsd(sel1, sel2, sel1->selected, ts1->pos, ts2->pos, weight, &rmsd); delete sel1; delete sel2; delete [] weight; if (rc < 0) { PyErr_SetString(PyExc_ValueError, measure_error(rc)); return NULL; } return PyFloat_FromDouble(rmsd); }
static PyObject *minmax(PyObject *self, PyObject *args) { int molid, frame; PyObject *selected; if (!PyArg_ParseTuple(args, (char *)"iiO!", &molid, &frame, &PyTuple_Type, &selected)) return NULL; // bad args VMDApp *app = get_vmdapp(); AtomSel *sel = sel_from_py(molid, frame, selected, app); if (!sel) return NULL; const Timestep *ts = app->moleculeList->mol_from_id(molid)->get_frame(frame); if (!ts) { PyErr_SetString(PyExc_ValueError, "No coordinates in selection"); delete sel; return NULL; } float min[3], max[3]; int rc = measure_minmax(sel->num_atoms, sel->on, ts->pos, NULL, min, max); delete sel; if (rc < 0) { PyErr_SetString(PyExc_ValueError, measure_error(rc)); return NULL; } PyObject *mintuple, *maxtuple, *result; mintuple = PyTuple_New(3); maxtuple = PyTuple_New(3); result = PyTuple_New(2); for (int i=0; i<3; i++) { PyTuple_SET_ITEM(mintuple, i, PyFloat_FromDouble(min[i])); PyTuple_SET_ITEM(maxtuple, i, PyFloat_FromDouble(max[i])); } PyTuple_SET_ITEM(result, 0, mintuple); PyTuple_SET_ITEM(result, 1, maxtuple); return result; }
static PyObject *sasa(PyObject *self, PyObject *args, PyObject *keywds) { int molid = -1, frame = -1; float srad = 0; PyObject *selobj = NULL, *restrictobj = NULL; int samples = -1; const int *sampleptr = NULL; PyObject *pointsobj = NULL; static char *kwlist[] = { (char *)"srad", (char *)"molid", (char *)"frame", (char *)"selected", (char *)"samples", (char *)"points", (char *)"restrict" }; if (!PyArg_ParseTupleAndKeywords(args, keywds, (char *)"fiiO!|iO!O!:atomselection.sasa", kwlist, &srad, &molid, &frame, &PyTuple_Type, &selobj, &samples, &PyList_Type, &pointsobj, &PyTuple_Type, &restrictobj)) return NULL; // validate srad if (srad < 0) { PyErr_SetString(PyExc_ValueError, (char *)"atomselect.sasa: srad must be non-negative."); return NULL; } // validate selection VMDApp *app = get_vmdapp(); AtomSel *sel = sel_from_py(molid, frame, selobj, app); if (!sel) return NULL; // fetch the radii and coordinates const float *radii = app->moleculeList->mol_from_id(sel->molid())->extraflt.data("radius"); const float *coords = sel->coordinates(app->moleculeList); // if samples was given and is valid, use it if (samples > 1) sampleptr = &samples; // if restrict is given, validate it AtomSel *restrictsel = NULL; if (restrictobj) { if (!(restrictsel = sel_from_py(molid, frame, restrictobj, app))) { delete sel; return NULL; } } // if points are requested, fetch them ResizeArray<float> sasapts; ResizeArray<float> *sasaptsptr = pointsobj ? &sasapts : NULL; // go! float sasa = 0; int rc = measure_sasa(sel, coords, radii, srad, &sasa, sasaptsptr, restrictsel, sampleptr); delete sel; delete restrictsel; if (rc) { PyErr_SetString(PyExc_ValueError, (char *)measure_error(rc)); return NULL; } // append surface points to the provided list object. if (pointsobj) { for (int i=0; i<sasapts.num(); i++) { PyList_Append(pointsobj, PyFloat_FromDouble(sasapts[i])); } } // return the total SASA. return PyFloat_FromDouble(sasa); }
static PyObject *py_align(PyObject *self, PyObject *args) { int selmol, selframe, refmol, refframe, movemol, moveframe; PyObject *selobj, *refobj, *moveobj, *weightobj = NULL; if (!PyArg_ParseTuple(args, (char *)"iiO!iiO!iiO!O:atomselection.align", &selmol, &selframe, &PyTuple_Type, &selobj, &refmol, &refframe, &PyTuple_Type, &refobj, &movemol, &moveframe, &PyTuple_Type, &moveobj, &weightobj)) return NULL; // check if movemol is -1. If so, use the sel molecule and timestep instead if (movemol == -1) { movemol = selmol; moveobj = NULL; } VMDApp *app = get_vmdapp(); AtomSel *sel=NULL, *ref=NULL, *move=NULL; if (!(sel = sel_from_py(selmol, selframe, selobj, app)) || !(ref = sel_from_py(refmol, refframe, refobj, app)) || !(move = sel_from_py(movemol, moveframe, moveobj, app))) { delete sel; delete ref; delete move; return NULL; } const float *selts, *refts; float *movets; if (!(selts = sel->coordinates(app->moleculeList)) || !(refts = ref->coordinates(app->moleculeList)) || !(movets = move->coordinates(app->moleculeList))) { delete sel; delete ref; delete move; PyErr_SetString(PyExc_ValueError, "No coordinates in selection"); return NULL; } float *weight = parse_weight(sel, weightobj); if (!weight) { delete sel; delete ref; delete move; return NULL; } // Find the matrix that aligns sel with ref. Apply the transformation to // the atoms in move. // XXX need to add support for the "order" parameter as in Tcl. Matrix4 mat; int rc = measure_fit(sel, ref, selts, refts, weight, NULL, &mat); delete [] weight; delete sel; delete ref; if (rc < 0) { delete move; PyErr_SetString(PyExc_ValueError, (char *)measure_error(rc)); return NULL; } for (int i=0; i<move->num_atoms; i++) { if (move->on[i]) { float *pos = movets+3*i; mat.multpoint3d(pos, pos); } } Molecule *mol = app->moleculeList->mol_from_id(move->molid()); mol->force_recalc(DrawMolItem::MOL_REGEN); delete move; Py_INCREF(Py_None); return Py_None; }
static PyObject *contacts(PyObject *self, PyObject *args) { int mol1, frame1, mol2, frame2; PyObject *selected1, *selected2; float cutoff; if (!PyArg_ParseTuple(args, (char *)"iiO!iiO!f:atomselection.contacts", &mol1, &frame1, &PyTuple_Type, &selected1, &mol2, &frame2, &PyTuple_Type, &selected2, &cutoff)) return NULL; VMDApp *app = get_vmdapp(); AtomSel *sel1 = sel_from_py(mol1, frame1, selected1, app); AtomSel *sel2 = sel_from_py(mol2, frame2, selected2, app); if (!sel1 || !sel2) { delete sel1; delete sel2; return NULL; } const float *ts1 = sel1->coordinates(app->moleculeList); const float *ts2 = sel2->coordinates(app->moleculeList); if (!ts1 || !ts2) { PyErr_SetString(PyExc_ValueError, "No coordinates in selection"); delete sel1; delete sel2; return NULL; } Molecule *mol = app->moleculeList->mol_from_id(mol1); GridSearchPair *pairlist = vmd_gridsearch3( ts1, sel1->num_atoms, sel1->on, ts2, sel2->num_atoms, sel2->on, cutoff, -1, (sel1->num_atoms + sel2->num_atoms) * 27); delete sel1; delete sel2; GridSearchPair *p, *tmp; PyObject *list1 = PyList_New(0); PyObject *list2 = PyList_New(0); PyObject *tmp1; PyObject *tmp2; for (p=pairlist; p != NULL; p=tmp) { // throw out pairs that are already bonded MolAtom *a1 = mol->atom(p->ind1); if (mol1 != mol2 || !a1->bonded(p->ind2)) { // Needed to avoid a memory leak. Append increments the refcount // of whatever gets added to it, but so does PyInt_FromLong. // Without a decref, the integers created never have their refcount // go to zero, and you leak memory. tmp1 = PyInt_FromLong(p->ind1); tmp2 = PyInt_FromLong(p->ind2); PyList_Append(list1, tmp1); PyList_Append(list2, tmp2); Py_DECREF(tmp1); Py_DECREF(tmp2); } tmp = p->next; free(p); } PyObject *result = PyList_New(2); PyList_SET_ITEM(result, 0, list1); PyList_SET_ITEM(result, 1, list2); return result; }