00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "py_commands.h"
00022 #include "VMDApp.h"
00023 #include "Measure.h"
00024
00025 static const char bond_doc[] =
00026 "Measures the distance between the atom1 and atom2 over the trajectory, either\n"
00027 "at the given frame or over frames from first to last. Distances between atoms\n"
00028 "in different molecules can be measured by giving specific molids\n\n"
00029 "Args:\n"
00030 " atom1 (int): Index of first atom\n"
00031 " atom2 (int): Index of second atom\n"
00032 " molid (int): Molecule ID of first atom, defaults to top molecule\n"
00033 " molid2 (int): Molecule ID of second atom, if different. (optional)\n"
00034 " frame (int): Measure distance in this single frame. Defaults to current\n"
00035 " first (int): For measuring multiple frames, first frame to measure\n"
00036 " last (int): For measuring multiple, last frame to measure\n"
00037 "Returns:\n"
00038 " (list of float): Distance between atoms for given frame(s)";
00039 static PyObject *py_measure_bond(PyObject *self, PyObject *args, PyObject *kwargs) {
00040 const char *kwlist[] = {"atom1", "atom2", "molid", "molid2", "frame", "first",
00041 "last", NULL};
00042 int first=-1, last=-1, frame=-1;
00043 PyObject *returnlist = NULL;
00044 int atmid[2], i;
00045 int molid[2] = {-1, -1};
00046
00047 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|iiiii:measure.bond",
00048 (char**) kwlist, &atmid[0], &atmid[1],
00049 &molid[0], &molid[1], &frame, &first, &last))
00050 return NULL;
00051
00052 VMDApp *app;
00053 if (!(app = get_vmdapp()))
00054 return NULL;
00055
00056
00057 if (molid[0] == -1)
00058 molid[0] = app->molecule_top();
00059
00060 if (molid[1] == -1)
00061 molid[1] = molid[0];
00062
00063
00064 if (frame != -1 && (first != -1 || last != -1)) {
00065 PyErr_Warn(PyExc_SyntaxWarning, "frame as well as first or last were "
00066 "specified.\nReturning value for just the "
00067 "frame");
00068 first = -1;
00069 last = -1;
00070 }
00071
00072
00073 ResizeArray<float> gValues(1024);
00074 int ret_val = measure_geom(app->moleculeList, molid, atmid, &gValues, frame,
00075 first, last, molid[0], MEASURE_BOND);
00076 if (ret_val < 0) {
00077 PyErr_SetString(PyExc_RuntimeError, measure_error(ret_val));
00078 return NULL;
00079 }
00080
00081
00082 int numvalues = gValues.num();
00083 if (!(returnlist = PyList_New(numvalues)))
00084 goto failure;
00085
00086 for (i = 0; i < numvalues; i++) {
00087 PyList_SET_ITEM(returnlist, i, PyFloat_FromDouble(gValues[i]));
00088
00089
00090 if (PyErr_Occurred())
00091 goto failure;
00092 }
00093 return returnlist;
00094
00095 failure:
00096 PyErr_SetString(PyExc_ValueError, "Couldn't build list of distances");
00097 Py_XDECREF(returnlist);
00098 return NULL;
00099 }
00100
00101
00102 static const char angle_doc[] =
00103 "Measure angles between given atoms over a trajectory. Can specify multiple\n"
00104 "molids to measure angles between atoms in different molecules.\n\n"
00105 "Args:\n"
00106 " atom1 (int): Index of first atom\n"
00107 " atom2 (int): Index of second atom\n"
00108 " atom3 (int): Index of third atom\n"
00109 " molid (int): Molecule ID of first atom. Defaults to top molecule\n"
00110 " molid2 (int): Molecule ID of second atom, if different from first molid\n"
00111 " molid3 (int): Molecule ID of third atom, if different from first molid\n"
00112 " frame (int): Single frame to measure angle in. Defaults to current frame\n"
00113 " first (int): First frame in range to measure in, for multiple frames\n"
00114 " last (int): Last frame in range to measure in, for multiple frames\n"
00115 "Returns:\n"
00116 " (list of float): Angle as measured in frame(s)";
00117 static PyObject *py_measure_angle(PyObject *self, PyObject *args, PyObject *kwargs) {
00118 const char *kwlist[] = {"atom1", "atom2", "atom3", "molid", "molid2",
00119 "molid3", "frame", "first", "last", NULL};
00120 int first=-1, last=-1, frame=-1;
00121 int molid[3] = {-1, -1, -1};
00122 PyObject *returnlist;
00123 int atmid[3];
00124
00125 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iii|iiiiii:measure.angle",
00126 (char**) kwlist, &atmid[0], &atmid[1],
00127 &atmid[2], &molid[0], &molid[1], &molid[2],
00128 &frame, &first, &last))
00129 return NULL;
00130
00131 VMDApp *app;
00132 if (!(app = get_vmdapp()))
00133 return NULL;
00134
00135
00136 if (molid[0] == -1)
00137 molid[0] = app->molecule_top();
00138
00139
00140 if (molid[1] == -1)
00141 molid[1] = molid[0];
00142
00143 if (molid[2] == -1)
00144 molid[2] = molid[0];
00145
00146
00147 if (frame != -1 && (first != -1 || last != -1)) {
00148 PyErr_Warn(PyExc_SyntaxWarning, "frame as well as first or last were "
00149 "specified.\nReturning value for just the "
00150 "frame");
00151 first = -1;
00152 last = -1;
00153 }
00154
00155 ResizeArray<float> gValues(1024);
00156 int ret_val = measure_geom(app->moleculeList, molid, atmid, &gValues, frame,
00157 first, last, molid[0], MEASURE_ANGLE);
00158 if (ret_val < 0) {
00159 PyErr_SetString(PyExc_RuntimeError, measure_error(ret_val));
00160 return NULL;
00161 }
00162
00163
00164 int numvalues = gValues.num();
00165 returnlist = PyList_New(numvalues);
00166 for (int i = 0; i < numvalues; i++)
00167 PyList_SetItem(returnlist, i, Py_BuildValue("f", gValues[i]));
00168
00169
00170 if (PyErr_Occurred()) {
00171 PyErr_SetString(PyExc_ValueError, "Couldn't build list of angles");
00172 Py_DECREF(returnlist);
00173 return NULL;
00174 }
00175
00176 return returnlist;
00177 }
00178
00179
00180 static const char dihed_doc[] =
00181 "Measures the dihedral angle between atoms over the trajectory. Can specify\n"
00182 "multiple molecule IDs to measure over different loaded molecules.\n\n"
00183 "Args:\n"
00184 " atom1 (int): First atom in dihedral\n"
00185 " atom2 (int): Second atom in dihedral\n"
00186 " atom3 (int): Third atom in dihedral\n"
00187 " atom4 (int): Fourth atom in dihedral\n"
00188 " molid (int): Molecule ID to measure in. Defaults to top molecule\n"
00189 " molid2 (int): Molecule ID for second atom, if different from molid\n"
00190 " molid3 (int): Molecule ID for third atom, if different from molid\n"
00191 " molid4 (int): Molecule ID for fourth atom, if different from molid\n"
00192 " frame (int): Single frame to measure angle in. Defaults to current frame\n"
00193 " first (int): First frame in range to measure in, for multiple frames\n"
00194 " last (int): Last frame in range to measure in, for multiple frames\n"
00195 "Returns:\n"
00196 " (list of float): Dihedral as measured in frame(s)";
00197 static PyObject *py_measure_dihed(PyObject *self, PyObject *args, PyObject *kwargs) {
00198 const char *kwlist[] = {"atom1", "atom2", "atom3", "atom4", "molid", "molid2",
00199 "molid3", "molid4", "frame", "first", "last", NULL};
00200 int first=-1, last=-1, frame=-1;
00201 int molid[4] = {-1, -1, -1, -1};
00202 PyObject *returnlist;
00203 int atmid[4];
00204
00205 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iiii|iiiiiii:measure.dihedral",
00206 (char**) kwlist, &atmid[0], &atmid[1],
00207 &atmid[2], &atmid[3], &molid[0], &molid[1],
00208 &molid[2], &molid[3], &frame, &first, &last))
00209 return NULL;
00210
00211 VMDApp *app;
00212 if (!(app = get_vmdapp()))
00213 return NULL;
00214
00215
00216 if (molid[0] == -1)
00217 molid[0] = app->molecule_top();
00218
00219
00220 if (molid[1] == -1)
00221 molid[1] = molid[0];
00222
00223 if (molid[2] == -1)
00224 molid[2] = molid[0];
00225
00226 if (molid[3] == -1)
00227 molid[3] = molid[0];
00228
00229
00230 if (frame != -1 && (first != -1 || last != -1)) {
00231 PyErr_Warn(PyExc_SyntaxWarning, "frame as well as first or last were "
00232 "specified.\nReturning value for just the "
00233 "frame");
00234 first = -1;
00235 last = -1;
00236 }
00237
00238
00239 ResizeArray<float> gValues(1024);
00240 int ret_val = measure_geom(app->moleculeList, molid, atmid, &gValues, frame,
00241 first, last, molid[0], MEASURE_DIHED);
00242 if (ret_val < 0) {
00243 PyErr_SetString(PyExc_RuntimeError, measure_error(ret_val));
00244 return NULL;
00245 }
00246
00247
00248 int numvalues = gValues.num();
00249 returnlist = PyList_New(numvalues);
00250 for (int i = 0; i < numvalues; i++)
00251 PyList_SetItem(returnlist, i, Py_BuildValue("f", gValues[i]));
00252
00253
00254 if (PyErr_Occurred()) {
00255 PyErr_SetString(PyExc_ValueError, "Couldn't build list of dihedrals");
00256 Py_DECREF(returnlist);
00257 return NULL;
00258 }
00259
00260 return returnlist;
00261 }
00262
00263
00264 static PyMethodDef methods[] = {
00265 {"bond", (PyCFunction)py_measure_bond, METH_VARARGS | METH_KEYWORDS, bond_doc},
00266 {"angle", (PyCFunction)py_measure_angle, METH_VARARGS | METH_KEYWORDS, angle_doc},
00267 {"dihedral", (PyCFunction)py_measure_dihed, METH_VARARGS | METH_KEYWORDS, dihed_doc},
00268 {NULL, NULL}
00269 };
00270
00271
00272 static const char measure_moddoc[] =
00273 "Methods to measure bonds, angles, or dihedrals in loaded molecules";
00274
00275
00276 #if PY_MAJOR_VERSION >= 3
00277 static struct PyModuleDef measuredef = {
00278 PyModuleDef_HEAD_INIT,
00279 "measure",
00280 measure_moddoc,
00281 -1,
00282 methods,
00283 };
00284 #endif
00285
00286
00287 PyObject* initmeasure() {
00288 #if PY_MAJOR_VERSION >= 3
00289 PyObject *m = PyModule_Create(&measuredef);
00290 #else
00291 PyObject *m = Py_InitModule3("measure", methods, measure_moddoc);
00292 #endif
00293 return m;
00294 }