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

py_commands.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2016 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_commands.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.23 $       $Date: 2021/09/23 16:37:07 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *  Core VMD Python interface
00019  ***************************************************************************/
00020 
00021 #include "py_commands.h"
00022 #include "VMDApp.h"
00023 #include "Molecule.h"
00024 #include "MoleculeList.h"
00025 
00026 /*
00027 
00028 Some distributed versions of VMD are linked against the Python 2.0 
00029 library.  The following BeOpen license agreement permits us to use the 
00030 Python 2.0 libraries in this fashion.  The BeOpen license agreement is in
00031 no way applicable to the license under which VMD itself is distributed;
00032 persuant to item 2 below, we merely include a copy of the BeOpen license
00033 to indicate our use of the BeOpen software.
00034 
00035 HISTORY OF THE SOFTWARE
00036 =======================
00037 
00038 Python was created in the early 1990s by Guido van Rossum at Stichting
00039 Mathematisch Centrum (CWI) in the Netherlands as a successor of a
00040 language called ABC.  Guido is Python's principal author, although it
00041 includes many contributions from others.  The last version released
00042 from CWI was Python 1.2.  In 1995, Guido continued his work on Python
00043 at the Corporation for National Research Initiatives (CNRI) in Reston,
00044 Virginia where he released several versions of the software.  Python
00045 1.6 was the last of the versions released by CNRI.  In 2000, Guido and
00046 the Python core developement team moved to BeOpen.com to form the
00047 BeOpen PythonLabs team (www.pythonlabs.com).  Python 2.0 is the first
00048 release from PythonLabs.  Thanks to the many outside volunteers who
00049 have worked under Guido's direction to make this release possible.
00050 
00051 
00052 
00053 BEOPEN.COM TERMS AND CONDITIONS FOR PYTHON 2.0
00054 ==============================================
00055 
00056 BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
00057 -----------------------------------------------------
00058 
00059 1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
00060 office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
00061 Individual or Organization ("Licensee") accessing and otherwise using
00062 this software in source or binary form and its associated
00063 documentation ("the Software").
00064 
00065 2. Subject to the terms and conditions of this BeOpen Python License
00066 Agreement, BeOpen hereby grants Licensee a non-exclusive,
00067 royalty-free, world-wide license to reproduce, analyze, test, perform
00068 and/or display publicly, prepare derivative works, distribute, and
00069 otherwise use the Software alone or in any derivative version,
00070 provided, however, that the BeOpen Python License is retained in the
00071 Software, alone or in any derivative version prepared by Licensee.
00072 
00073 3. BeOpen is making the Software available to Licensee on an "AS IS"
00074 basis.  BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
00075 IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
00076 DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
00077 FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
00078 INFRINGE ANY THIRD PARTY RIGHTS.
00079 
00080 4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
00081 SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
00082 AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
00083 DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
00084 
00085 5. This License Agreement will automatically terminate upon a material
00086 breach of its terms and conditions.
00087 
00088 6. This License Agreement shall be governed by and interpreted in all
00089 respects by the law of the State of California, excluding conflict of
00090 law provisions.  Nothing in this License Agreement shall be deemed to
00091 create any relationship of agency, partnership, or joint venture
00092 between BeOpen and Licensee.  This License Agreement does not grant
00093 permission to use BeOpen trademarks or trade names in a trademark
00094 sense to endorse or promote products or services of Licensee, or any
00095 third party.  As an exception, the "BeOpen Python" logos available at
00096 http://www.pythonlabs.com/logos.html may be used according to the
00097 permissions granted on that web page.
00098 
00099 7. By copying, installing or otherwise using the software, Licensee
00100 agrees to be bound by the terms and conditions of this License
00101 Agreement.
00102 
00103 
00104 */
00105 
00106 // Wrapper function for getting char* from a Python string, with 2/3 ifdefs
00107 const char *as_constcharptr(PyObject *target) {
00108   const char *result;
00109 #if PY_MAJOR_VERSION >= 3
00110   result = PyUnicode_AsUTF8(target);
00111 #else
00112   result = PyString_AsString(target);
00113 #endif
00114 
00115   if (!result || PyErr_Occurred()) {
00116     PyErr_SetString(PyExc_ValueError, "cannot convert PyObject to char*");
00117     return NULL;
00118   }
00119 
00120   return result;
00121 }
00122 
00123 
00124 // Wrapper function for turning char* into a Python string, with 2/3 ifdefs
00125 PyObject* as_pystring(const char *target) {
00126   PyObject *result;
00127   if (!target) {
00128     PyErr_SetString(PyExc_ValueError, "cannot return null string");
00129     return NULL;
00130   }
00131 
00132 #if PY_MAJOR_VERSION >= 3
00133   result = PyUnicode_FromString(target);
00134 #else
00135   result = PyString_FromString(target);
00136 #endif
00137 
00138   if (!result) {
00139     PyErr_Format(PyExc_ValueError, "cannot convert char* '%s'", target);
00140     return NULL;
00141   }
00142 
00143   // Separate this so it gives a more helpful error message
00144   if (PyErr_Occurred())
00145     return NULL;
00146 
00147   return result;
00148 }
00149 
00150 
00151 // Wrapper function for checking if a PyObject is a string, with 2/3 ifdefs
00152 int is_pystring(const PyObject *target) {
00153 #if PY_MAJOR_VERSION >= 3
00154   return PyUnicode_Check(target);
00155 #else
00156   return PyString_Check(target);
00157 #endif
00158 }
00159 
00160 
00161 // Wrapper function for turning int into a Python int/long, with 2/3 ifdefs
00162 PyObject* as_pyint(int target) {
00163   PyObject *result;
00164 #if PY_MAJOR_VERSION >= 3
00165   result = PyLong_FromLong((long) target);
00166 #else
00167   result = PyInt_FromLong((long) target);
00168 #endif
00169 
00170   if (!result) {
00171     PyErr_Format(PyExc_ValueError, "cannot convert int %d", target);
00172     return NULL;
00173   }
00174 
00175   // Separate this so it gives a more helpful error message
00176   if (PyErr_Occurred())
00177     return NULL;
00178 
00179   return result;
00180 }
00181 
00182 
00183 // Wrapper function for getting int from a Python object, with 2/3 ifdefs
00184 int as_int(PyObject *target) {
00185   int result;
00186   if (!is_pyint(target)) {
00187     PyErr_SetString(PyExc_ValueError, "Non-integer Python object in as_int");
00188     return -1;
00189   }
00190 
00191 #if PY_MAJOR_VERSION >= 3
00192   result = (int) PyLong_AsLong(target);
00193 #else
00194   result = (int) PyInt_AsLong(target);
00195 #endif
00196 
00197   return result;
00198 }
00199 
00200 
00201 // Wrapper function to check if a python object is an int
00202 int is_pyint(PyObject *target) {
00203 #if PY_MAJOR_VERSION >= 3
00204   if (PyLong_Check(target)) {
00205     return 1;
00206   } else {
00207     // Numpy integers don't actually inherit from long in python 3, 
00208     // since python 3 longs aren't fixed width like they were in python 2.
00209     // Need to do something fancier to check if the object is a numpy.int32 
00210     // or numpy.int64.  PyLong_AsLong can handle both.
00211     const char *type = Py_TYPE(target)->tp_name;
00212     return (!strcmp("numpy.int32", type)) || (!strcmp("numpy.int64", type));
00213   }
00214 #else
00215   return PyInt_Check(target);
00216 #endif
00217 }
00218 
00219 
00220 //
00221 // The VMDApp instance will be found in the VMDApp module, under the
00222 // VMDApp dictionary entry.  Got it?  
00223 //
00224 VMDApp *get_vmdapp() {
00225 #if PY_MAJOR_VERSION >= 3
00226   PyObject *module = PyImport_ImportModule("builtins");
00227 #else
00228   PyObject *module = PyImport_ImportModule("__builtin__");
00229 #endif
00230   if (!module)
00231     return NULL;
00232 
00233   PyObject *module_dict = PyModule_GetDict(module);
00234   if (!module_dict)
00235       return NULL;
00236 
00237 #if PY_MAJOR_VERSION >= 3
00238   // Python 3 uses a "capsule" to store C pointers
00239   PyObject *c_obj = PyDict_GetItemString(module_dict, "-vmdapp-");
00240   if (!c_obj || PyErr_Occurred())
00241     return NULL;
00242 
00243   if (PyCapsule_CheckExact(c_obj))
00244     return (VMDApp *)PyCapsule_GetPointer(c_obj, "-vmdapp-");
00245 
00246 #else
00247   // Python 2 instead uses the idea of a "C Object"
00248   PyObject *c_obj = PyDict_GetItemString(module_dict, "-vmdapp-");
00249   if (!c_obj || PyErr_Occurred())
00250     return NULL;
00251 
00252   if (PyCObject_Check(c_obj))
00253     return (VMDApp *)PyCObject_AsVoidPtr(c_obj);
00254 #endif
00255 
00256   return NULL;
00257 }
00258 
00259 
00260 void set_vmdapp(VMDApp *app) {
00261 #if PY_MAJOR_VERSION >= 3
00262   PyObject *mod = PyImport_ImportModule("builtins");
00263   PyObject *cap = PyCapsule_New(app, "-vmdapp-", NULL);
00264   PyObject_SetAttrString(mod, "-vmdapp-", cap);
00265 #else
00266   PyObject *mod = PyImport_ImportModule("__builtin__");
00267   PyObject_SetAttrString(mod, "-vmdapp-", 
00268       PyCObject_FromVoidPtr(app, NULL));
00269 #endif
00270   Py_DECREF(mod);
00271 }
00272 
00273 
00274 int py_array_from_obj(PyObject *obj, float *arr) {
00275   PyObject *seqdata = NULL, *elem;
00276   int i;
00277 
00278   if (!(seqdata=PySequence_Fast(obj, "Coordinate argument must be a sequence")))
00279     goto failure;
00280 
00281   if (PySequence_Fast_GET_SIZE(seqdata) != 3) {
00282     PyErr_SetString(PyExc_ValueError, "Coordinate must have length 3");
00283     goto failure;
00284   }
00285 
00286   for (i = 0; i < 3; i++) {
00287     elem = PySequence_Fast_GET_ITEM(seqdata, i);
00288 
00289     arr[i] = PyFloat_AsDouble(elem);
00290     if (PyErr_Occurred()) {
00291       PyErr_SetString(PyExc_ValueError, "Problem unpacking coordinate");
00292       goto failure;
00293     }
00294   }
00295   return 1;  // successful return
00296 
00297 failure:
00298   Py_XDECREF(seqdata);
00299   return 0;
00300 }
00301 
00302 Timestep *parse_timestep(VMDApp *app, int molid, int frame) {
00303   Timestep *ts = NULL;
00304   Molecule *mol;
00305 
00306   // Get molecule from molid or top molecule
00307   if (molid < 0)
00308     molid = app->molecule_top();
00309   mol = app->moleculeList->mol_from_id(molid);
00310 
00311   if (!mol) {
00312     PyErr_Format(PyExc_ValueError, "Invalid molecule id '%d'", molid);
00313     return NULL;
00314   }
00315 
00316   // Get frame number
00317   if (frame == -1)
00318     ts = mol->current();
00319   else if (frame == -2)
00320     ts = mol->get_last_frame();
00321   else
00322     ts = mol->get_frame(frame);
00323 
00324   if (!ts) {
00325     PyErr_Format(PyExc_ValueError, "Invalid frame '%d'", frame);
00326     return NULL;
00327   }
00328 
00329   return ts;
00330 }
00331 
00332 
00333 // Helper function to check if molid is valid and set exception if not
00334 int valid_molid(int molid, VMDApp *app) {
00335   if (!app->molecule_valid_id(molid)) {
00336     PyErr_Format(PyExc_ValueError, "Invalid molecule id '%d'", molid);
00337     return 0;
00338   }
00339   return 1;
00340 }
00341 
00342 
00343 // extract vector from sequence object.  Return success.
00344 int py_get_vector(PyObject *matobj, int n, float *vec) {
00345   PyObject *fastval = NULL;
00346   PyObject *fval;
00347   int i;
00348 
00349   if (!PySequence_Check(matobj) || PySequence_Size(matobj) != n) {
00350     PyErr_SetString(PyExc_ValueError, "vector has incorrect size");
00351     return 0;
00352   }
00353 
00354   if (!(fastval = PySequence_Fast(matobj, "Invalid sequence")))
00355     goto failure;
00356 
00357   for (i = 0; i < n; i++) {
00358     fval = PySequence_Fast_GET_ITEM(fastval, i);
00359 
00360     if (!PyFloat_Check(fval)) {
00361       PyErr_SetString(PyExc_TypeError, "vector must contain only floats");
00362       goto failure;
00363     }
00364 
00365     vec[i] = PyFloat_AsDouble(fval);
00366     if (PyErr_Occurred())
00367       goto failure;
00368   }
00369 
00370   Py_DECREF(fastval);
00371   return 1;
00372 
00373 failure:
00374   Py_XDECREF(fastval);
00375   return 0;
00376 }
00377 
00378 
00379 // Converter function for boolean arguments
00380 int convert_bool(PyObject *obj, void *boolval) {
00381   if (!PyObject_TypeCheck(obj, &PyBool_Type)) {
00382     PyErr_SetString(PyExc_TypeError, "expected a boolean");
00383     return 0;
00384   }
00385 
00386   *((int*)(boolval)) = PyObject_IsTrue(obj);
00387   return 1; // success
00388 }
00389 
00390 
00391 _py3_inittab py_initializers[] = {
00392    {"animate", initanimate},
00393    {"atomsel", initatomsel},
00394    {"axes", initaxes},
00395    {"color", initcolor},
00396    {"display", initdisplay},
00397    {"graphics", initgraphics},
00398 #ifdef VMDIMD
00399    {"imd", initimd},
00400 #endif
00401    {"label", initlabel},
00402    {"material", initmaterial},
00403    {"molecule", initmolecule},
00404    {"molrep", initmolrep},
00405    {"mouse", initmouse},
00406    {"render", initrender},
00407    {"trans", inittrans},
00408    {"measure", initmeasure},
00409    {"topology", inittopology},
00410    {"selection", initselection},
00411    {"vmdcallbacks", initvmdcallbacks},
00412    {"vmdmenu", initvmdmenu},
00413 #ifdef VMDNUMPY
00414    {"vmdnumpy", initvmdnumpy},
00415 #endif
00416    {NULL, NULL},
00417 };
00418 

Generated on Thu Mar 28 02:44:02 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002