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 }