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 Mon Nov 17 02:47:03 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /