Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

py_measure.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2019 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: py_measure.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.11 $       $Date: 2019/06/05 14:50:54 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   Code to measure atom distances, angles, dihedrals, etc.
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   // If molid(s) unset, use top molecule
00057   if (molid[0] == -1)
00058     molid[0] = app->molecule_top();
00059 
00060   if (molid[1] == -1)
00061     molid[1] = molid[0];
00062 
00063   // Need either (first, last) or a single frame.
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   //Calculate the bond length
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   // Build the list containing all measured distances
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     // XXX this is inconsistent with the other two, why special?
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   // Default to top molecule
00136   if (molid[0] == -1)
00137     molid[0] = app->molecule_top();
00138 
00139   // Other two molids default to the first molid
00140   if (molid[1] == -1)
00141     molid[1] = molid[0];
00142 
00143   if (molid[2] == -1)
00144     molid[2] = molid[0];
00145 
00146   // Warn if passing a single frame and a range
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     //Calculate the angle
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   //Build the python list.
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   // Remove reference to list if something went wrong
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   // Molid defaults to top molecule
00216   if (molid[0] == -1)
00217     molid[0] = app->molecule_top();
00218 
00219   // Other molecule IDs default to molid
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   // Warn if both frame and range of frames are given
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   //Calculate the dihedral angle
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   //Build the python list.
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   // Remove reference to list if something went wrong
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 }

Generated on Thu Apr 18 02:45:29 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002