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

py_label.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2011 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_label.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.22 $       $Date: 2011/02/01 18:59:13 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *  Python interface to labelling functions
00019  ***************************************************************************/
00020 
00021 #include "py_commands.h"
00022 #include "VMDApp.h"
00023 #include "GeometryList.h"
00024 #include "Molecule.h"
00025 #include "MoleculeList.h"
00026 #include "config.h"
00027 
00028 // helper function to turn a GeometryMol object into a dictionary
00029 static PyObject *geom2dict(GeometryMol *g) {
00030   
00031   PyObject *newdict = PyDict_New();
00032   {
00033     int n = g->items();
00034     PyObject *molid_tuple = PyTuple_New(n);
00035     PyObject *atomid_tuple = PyTuple_New(n);
00036     for (int i=0; i<n; i++) {
00037       PyTuple_SET_ITEM(molid_tuple, i, PyInt_FromLong(g->obj_index(i)));
00038       PyTuple_SET_ITEM(atomid_tuple, i, PyInt_FromLong(g->com_index(i)));
00039     } 
00040     PyDict_SetItemString(newdict, (char *)"molid", molid_tuple);
00041     PyDict_SetItemString(newdict, (char *)"atomid", atomid_tuple);
00042   }
00043   {
00044     PyObject *value;
00045     if (g->ok())
00046       value = PyFloat_FromDouble(g->calculate());
00047     else
00048       value = Py_None;
00049     PyDict_SetItemString(newdict, (char *)"value", value);
00050   }
00051   {
00052     PyObject *on = PyInt_FromLong(g->displayed() ? 1 : 0);
00053     PyDict_SetItemString(newdict, (char *)"on", on);
00054   }
00055   if (PyErr_Occurred()) {
00056     Py_DECREF(newdict);
00057     return NULL;
00058   } 
00059   return newdict; 
00060 }
00061 
00062 // listall(category) - return a list of labels for the given label category. 
00063 // labels will be returned as dictionary objects with the following keys:
00064 // molid, atomid, value, on.  molid and atomid will be tuples, value will
00065 // be either a float or PyNone, and on will be 1 or 0.
00066 static PyObject *listall(PyObject *self, PyObject *args) {
00067   char *type;
00068   if (!PyArg_ParseTuple(args, (char *)"s:label.listall", &type))
00069     return NULL;
00070 
00071   VMDApp *app = get_vmdapp();
00072   int cat = app->geometryList->geom_list_index(type);
00073   if (cat < 0) {
00074     PyErr_SetString(PyExc_ValueError, (char *)"Unknown label category");
00075     return NULL;
00076   }
00077   GeomListPtr glist = app->geometryList->geom_list(cat);
00078   int gnum = glist->num(); 
00079   PyObject *newlist = PyList_New(gnum);
00080   for (int i=0; i<gnum; i++) {
00081     PyObject *obj = geom2dict((*glist)[i]);
00082     if (obj == NULL) {
00083       Py_DECREF(newlist);
00084       return NULL;
00085     }
00086     PyList_SET_ITEM(newlist, i, geom2dict((*glist)[i]));
00087   }
00088   return newlist;
00089 } 
00090 
00091 // add(category, (molids), (atomids))
00092 static PyObject *label_add(PyObject *self, PyObject *args) {
00093   char *type;
00094   PyObject *molids, *atomids;
00095   int i;
00096   if (!PyArg_ParseTuple(args, (char *)"sO!O!:label.add", 
00097     &type, &PyTuple_Type, &molids, &PyTuple_Type, &atomids))
00098     return NULL;
00099 
00100   VMDApp *app = get_vmdapp();
00101   MoleculeList *mlist = app->moleculeList;
00102   int cat = app->geometryList->geom_list_index(type);
00103   if (cat < 0) {
00104     PyErr_SetString(PyExc_ValueError, (char *)"Unknown label category");
00105     return NULL;
00106   }
00107   int numitems;
00108   if (PyTuple_Size(molids) == 1 && PyTuple_Size(atomids) == 1)
00109     numitems = 1;
00110   else if (PyTuple_Size(molids) == 2 && PyTuple_Size(atomids) == 2)
00111     numitems = 2; 
00112   else if (PyTuple_Size(molids) == 3 && PyTuple_Size(atomids) == 3)
00113     numitems = 3;
00114   else if (PyTuple_Size(molids) == 4 && PyTuple_Size(atomids) == 4)
00115     numitems = 4;
00116   else {
00117     PyErr_SetString(PyExc_TypeError, (char *)"label.add: 2nd and 3rd arguments"
00118       " must be tuples of size 1, 2, 3, or 4");
00119     return NULL;
00120   }
00121   int m[4], a[4];
00122   for (i=0; i<numitems; i++) {
00123     m[i] = PyInt_AsLong(PyTuple_GET_ITEM(molids, i));
00124     a[i] = PyInt_AsLong(PyTuple_GET_ITEM(atomids, i));
00125     if (PyErr_Occurred())
00126       return NULL;
00127     Molecule *mol = mlist->mol_from_id(m[i]);
00128     if (!mol) {
00129       PyErr_SetString(PyExc_ValueError, (char *)"Invalid molecule id");
00130       return NULL;
00131     }
00132     if (a[i] < 0 || a[i] >= mol->nAtoms) {
00133       PyErr_SetString(PyExc_ValueError, (char *)"Invalid atom id");
00134       return NULL;
00135     }
00136   } 
00137   // Add the label, but don't toggle the on/off status.  
00138   int ind = app->label_add(type, numitems, m, a, NULL, 0.0f, 0);
00139   if (ind < 0) {
00140     Py_INCREF(Py_None);
00141     return Py_None;
00142   }
00143   // Get the dict corresponding to this label.  The dict we return
00144   // corresponds to either the label we just created, or to an existing
00145   // label whose state we have not changed.  This makes it safe to use
00146   // label.add to get a proxy to a VMD label.
00147   GeomListPtr glist = app->geometryList->geom_list(cat);
00148   return geom2dict((*glist)[ind]);
00149 }
00150 
00151 // returns true if the given label object matches the given geometry object
00152 static int dict2geom(PyObject *dict, GeometryMol *g) {
00153   
00154   PyObject *molid = PyDict_GetItemString(dict, (char *)"molid");
00155   PyObject *atomid = PyDict_GetItemString(dict, (char *)"atomid");
00156   if (molid == NULL || atomid == NULL || 
00157       !PyTuple_Check(molid) || !PyTuple_Check(atomid)) {
00158     return 0;
00159   }
00160 
00161   int numitems = PyTuple_Size(molid);
00162   if (numitems != PyTuple_Size(atomid) || numitems != g->items()) {
00163     return 0;
00164   }
00165 
00166   for (int i=0; i<numitems; i++) {
00167     int m = PyInt_AsLong(PyTuple_GET_ITEM(molid, i));
00168     int a = PyInt_AsLong(PyTuple_GET_ITEM(atomid, i));
00169     if (PyErr_Occurred()) {
00170       PyErr_Clear();
00171       return 0;
00172     }
00173     if (m != g->obj_index(i) || a != g->com_index(i)) {
00174       return 0;
00175     }
00176   }
00177   return 1;
00178 }
00179    
00180 // show(category, labeldict)
00181 static PyObject *label_show(PyObject *self, PyObject *args) {
00182   char *type;
00183   PyObject *labeldict;
00184   if (!PyArg_ParseTuple(args, (char *)"sO!:label.show", 
00185     &type, &PyDict_Type, &labeldict))
00186     return NULL;
00187 
00188   VMDApp *app = get_vmdapp();
00189   int cat = app->geometryList->geom_list_index(type);
00190   if (cat < 0) {
00191     PyErr_SetString(PyExc_ValueError, (char *)"Unknown label category");
00192     return NULL;
00193   }
00194   GeomListPtr glist = app->geometryList->geom_list(cat);
00195   int gnum = glist->num();
00196   for (int i=0; i<gnum; i++) {
00197     if (dict2geom(labeldict, (*glist)[i])) {
00198       app->label_show(type, i, 1); // XXX check return code
00199       Py_INCREF(Py_None);
00200       return Py_None;
00201     }
00202   }
00203   PyErr_SetString(PyExc_ValueError, "Invalid labeldict.");
00204   return NULL;
00205 } 
00206  
00207 // hide(category, labeldict)
00208 // XXX cut 'n paste from show...
00209 static PyObject *label_hide(PyObject *self, PyObject *args) {
00210   char *type;
00211   PyObject *labeldict;
00212   if (!PyArg_ParseTuple(args, (char *)"sO!:label.hide", 
00213     &type, &PyDict_Type, &labeldict))
00214     return NULL;
00215 
00216   VMDApp *app = get_vmdapp();
00217   int cat = app->geometryList->geom_list_index(type);
00218   if (cat < 0) {
00219     PyErr_SetString(PyExc_ValueError, (char *)"Unknown label category");
00220     return NULL;
00221   }
00222   GeomListPtr glist = app->geometryList->geom_list(cat);
00223   int gnum = glist->num();
00224   for (int i=0; i<gnum; i++) {
00225     if (dict2geom(labeldict, (*glist)[i])) {
00226       app->label_show(type, i, 0); // XXX check return code
00227       Py_INCREF(Py_None);
00228       return Py_None;
00229     }
00230   }
00231   PyErr_SetString(PyExc_ValueError, "Invalid labeldict.");
00232   return NULL;
00233 } 
00234 
00235 // delete(category, labeldict)
00236 // XXX cut 'n paste from show...
00237 static PyObject *label_delete(PyObject *self, PyObject *args) {
00238   char *type;
00239   PyObject *labeldict;
00240   if (!PyArg_ParseTuple(args, (char *)"sO!:label.delete", 
00241     &type, &PyDict_Type, &labeldict))
00242     return NULL;
00243 
00244   VMDApp *app = get_vmdapp();
00245   int cat = app->geometryList->geom_list_index(type);
00246   if (cat < 0) {
00247     PyErr_SetString(PyExc_ValueError, (char *)"Unknown label category");
00248     return NULL;
00249   }
00250   GeomListPtr glist = app->geometryList->geom_list(cat);
00251   int gnum = glist->num();
00252   for (int i=0; i<gnum; i++) {
00253     if (dict2geom(labeldict, (*glist)[i])) {
00254       app->label_delete(type, i); // XXX check return code
00255       Py_INCREF(Py_None);
00256       return Py_None;
00257     }
00258   }
00259   PyErr_SetString(PyExc_ValueError, "Invalid labeldict.");
00260   return NULL;
00261 } 
00262 
00263 // return Python list of values for this label.  Return None if this label
00264 // has no values (e.g. Atom labels), or NULL on error.
00265 static PyObject *getvalues(GeometryMol *g) {
00266   if (!g->has_value()) {
00267     Py_INCREF(Py_None);
00268     return Py_None;
00269   }
00270   ResizeArray<float> gValues(1024);
00271   if (!g->calculate_all(gValues)) {
00272     PyErr_SetString(PyExc_ValueError, (char *)"Invalid label");
00273     return NULL;
00274   }
00275   const int n = gValues.num();
00276   PyObject *newlist = PyList_New(n);
00277   for (int i=0; i<n; i++) {
00278     PyList_SET_ITEM(newlist, i, PyFloat_FromDouble(gValues[i]));
00279   }
00280   return newlist;
00281 }
00282 
00283 // getvalues(category, labeldict) -> list
00284 // returns list containing value of label for every frame in the label
00285 // if the label contains atoms from more than one molecule, only the first
00286 // molecule is cycled (this the behavior of GeometryMol).
00287 // XXX Note: this command is bad: the GeometryMol::calculate_all method 
00288 // twiddles the frame of the molecule, so this command isn't read only as 
00289 // its semantics would imply.  But it should be possible to fix this 
00290 // in GeometryMol.
00291 static PyObject *label_getvalues(PyObject *self, PyObject *args) {
00292   char *type;
00293   PyObject *labeldict;
00294   if (!PyArg_ParseTuple(args, (char *)"sO!:label.getvalues",
00295     &type, &PyDict_Type, &labeldict))
00296     return NULL;
00297 
00298   VMDApp *app = get_vmdapp();
00299   int cat = app->geometryList->geom_list_index(type);
00300   if (cat < 0) {
00301     PyErr_SetString(PyExc_ValueError, (char *)"Unknown label category");
00302     return NULL;
00303   }
00304   GeomListPtr glist = app->geometryList->geom_list(cat);
00305   int gnum = glist->num();
00306   for (int i=0; i<gnum; i++) {
00307     if (dict2geom(labeldict, (*glist)[i])) 
00308       return getvalues((*glist)[i]);
00309   }
00310   PyErr_SetString(PyExc_ValueError, (char *)"Invalid label");
00311   return NULL;
00312 }
00313 
00314 static PyObject *label_textsize(PyObject *self, PyObject *args) {
00315   float newsize = -1;
00316   if (!PyArg_ParseTuple(args, (char *)"|f:label.textsize",
00317         &newsize))
00318     return NULL;
00319   VMDApp *app = get_vmdapp();
00320   if (newsize > 0) {
00321     app->label_set_text_size(newsize);
00322   }
00323   return Py_BuildValue("%f", app->label_get_text_size());
00324 }
00325 
00326 static PyObject *label_textthickness(PyObject *self, PyObject *args) {
00327   float newthick = -1;
00328   if (!PyArg_ParseTuple(args, (char *)"|f:label.textthickness",
00329         &newthick))
00330     return NULL;
00331   VMDApp *app = get_vmdapp();
00332   if (newthick > 0) {
00333     app->label_set_text_thickness(newthick);
00334   }
00335   return Py_BuildValue("%f", app->label_get_text_thickness());
00336 }
00337 
00338 
00339 static PyMethodDef LabelMethods[] = {
00340   {(char *)"listall", (vmdPyMethod)listall, METH_VARARGS },
00341   {(char *)"add", (vmdPyMethod)label_add, METH_VARARGS },
00342   {(char *)"show", (vmdPyMethod)label_show, METH_VARARGS },
00343   {(char *)"hide", (vmdPyMethod)label_hide, METH_VARARGS },
00344   {(char *)"delete", (vmdPyMethod)label_delete, METH_VARARGS },
00345   {(char *)"getvalues", (vmdPyMethod)label_getvalues, METH_VARARGS },
00346   {(char *)"textsize", (vmdPyMethod)label_textsize, METH_VARARGS },
00347   {(char *)"textthickness", (vmdPyMethod)label_textthickness, METH_VARARGS },
00348   {NULL, NULL}
00349 };
00350 
00351 void initlabel() {
00352   PyObject *m = Py_InitModule((char *)"label", LabelMethods);
00353   PyModule_AddStringConstant(m, (char *)"ATOM", (char *)"Atoms"); 
00354   PyModule_AddStringConstant(m, (char *)"BOND", (char *)"Bonds"); 
00355   PyModule_AddStringConstant(m, (char *)"ANGLE", (char *)"Angles"); 
00356   PyModule_AddStringConstant(m, (char *)"DIHEDRAL", (char *)"Dihedrals"); 
00357 }
00358  

Generated on Sun May 27 01:59:01 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002