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