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_topo.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.10 $ $Date: 2019年05月31日 07:07:48 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * Query and manipulate molecular topology information 00019 ***************************************************************************/ 00020 00021 #include "py_commands.h" 00022 #include "VMDApp.h" 00023 #include "Molecule.h" 00024 #include "MoleculeList.h" 00025 #include "DrawMolecule.h" 00026 00027 static const char bond_doc[] = "Get all unique bonds within a specified molecule. Optionally, can get bond\n" 00028 "type and order by modifying the type parameter\n\n" 00029 "Args:\n" 00030 " molid (int): Molecule ID to query. Defaults to top molecule\n" 00031 " type (bool): Whether to include bond type information in the result\n" 00032 " Defaults to False.\n" 00033 " orders (bool): Whether to include bond order information in the result\n" 00034 " Defaults to False.\n" 00035 "Returns:\n" 00036 " (list of lists) Information about each bond in the system. Each bond\n" 00037 " will be a list with the indices of the two atoms in the\n" 00038 " bond, followed by bond type (as a string) and order (as a float) if\n" 00039 " requested"; 00040 static PyObject* topo_get_bond(PyObject *self, PyObject *args, PyObject *kwargs) { 00041 const char *kwlist[] = {"molid", "type", "order", NULL}; 00042 PyObject *returnlist = NULL, *bond = NULL; 00043 int b_types = 0, b_orders = 0, molid = -1; 00044 PyObject *obtypes = Py_False; 00045 int i, j, types; 00046 Molecule *mol; 00047 00048 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|iOO&:topology.bonds", 00049 (char**) kwlist, &molid, &obtypes, 00050 convert_bool, &b_orders)) 00051 return NULL; 00052 00053 VMDApp *app; 00054 if (!(app = get_vmdapp())) 00055 return NULL; 00056 00057 // Check molid is valid 00058 if (molid == -1) 00059 molid = app->molecule_top(); 00060 00061 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00062 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00063 return NULL; 00064 } 00065 00066 if (PyBool_Check(obtypes)) { 00067 b_types = (obtypes == Py_True) ? 1 : 0; 00068 00069 // Handle deprecated types argument 00070 } else if (is_pyint(obtypes)) { 00071 // Check regular argument wasn't also passed 00072 if (kwargs && PyDict_GetItemString(kwargs, "order")) { 00073 PyErr_SetString(PyExc_ValueError, "Cannot specify deprecated type " 00074 "argument with new or orders arguments"); 00075 return NULL; 00076 } 00077 types = as_int(obtypes); 00078 00079 if (types == 3) 00080 b_types = b_orders = 1; 00081 else if (types == 2) 00082 b_orders = 1; 00083 else if (types == 1) 00084 b_types = 1; 00085 00086 PyErr_Warn(PyExc_DeprecationWarning, "type int keyword is now replaced by " 00087 "type and order booleans"); 00088 // Handle error if it's not a boolean 00089 } else { 00090 PyErr_SetString(PyExc_TypeError, "type keyword expected a bool"); 00091 return NULL; 00092 } 00093 00094 // Assume no bonds, and build the list from empty to avoid traversing 00095 // the entire bond list twice 00096 if (!(returnlist = PyList_New(0))) 00097 goto failure; 00098 00099 for (i = 0; i < mol->nAtoms - 1; i++) { // Last atom can add no new bonds. 00100 const MolAtom *atom = mol->atom(i); 00101 for (j = 0; j < atom->bonds; j++) { 00102 if (i < atom->bondTo[j]) { 00103 if (b_types && b_orders) { 00104 bond = Py_BuildValue("iisf", i, atom->bondTo[j], 00105 mol->bondTypeNames.name(mol->getbondtype(i, j)), 00106 mol->getbondorder(i, j)); 00107 } else if (b_types) { 00108 bond = Py_BuildValue("iis", i, atom->bondTo[j], 00109 mol->bondTypeNames.name(mol->getbondtype(i, j))); 00110 } else if (b_orders) { 00111 bond = Py_BuildValue("iif", i, atom->bondTo[j], 00112 mol->getbondorder(i, j)); 00113 } else { 00114 bond = Py_BuildValue("ii", i, atom->bondTo[j]); 00115 } 00116 00117 // Don't leak references with PyList_Append 00118 PyList_Append(returnlist, bond); 00119 Py_XDECREF(bond); 00120 if (PyErr_Occurred()) 00121 goto failure; 00122 } 00123 } 00124 } 00125 return returnlist; 00126 00127 failure: 00128 PyErr_SetString(PyExc_RuntimeError, "problem building bond list"); 00129 Py_XDECREF(returnlist); 00130 return NULL; 00131 } 00132 00133 00134 static const char angle_doc[] = 00135 "Get all unique angles within a specified molecule. Optionally, can get angle\n" 00136 "type as well\n\n" 00137 "Args:\n" 00138 " molid (int): Molecule ID to query. Defaults to top molecule\n" 00139 " type (bool): Whether to include angle type information in the result\n" 00140 " Defaults to False.\n" 00141 "Returns:\n" 00142 " (list of lists) Information about each angle in the system. Each angle \n" 00143 " will be a list with the indices of the three atoms comprising the\n" 00144 " angle, followed by angle type (as a string) if requested."; 00145 static PyObject* topo_get_angle(PyObject *self, PyObject *args, 00146 PyObject *kwargs) { 00147 const char *kwlist[] = {"molid", "type", NULL}; 00148 PyObject *returnlist = NULL; 00149 int molid = -1, types = 0; 00150 Molecule *mol; 00151 int i; 00152 00153 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii:topology.angle", 00154 (char**) kwlist, &molid, &types)) 00155 return NULL; 00156 00157 VMDApp *app; 00158 if (!(app = get_vmdapp())) 00159 return NULL; 00160 00161 if (molid == -1) 00162 molid = app->molecule_top(); 00163 00164 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00165 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00166 return NULL; 00167 } 00168 00169 if (!(returnlist = PyList_New(mol->num_angles()))) 00170 goto failure; 00171 00172 for (i=0; i<mol->num_angles(); i++) { 00173 PyObject* angle; 00174 if (types) { 00175 angle = Py_BuildValue("iiis", mol->angles[3*i], mol->angles[3*i+1], 00176 mol->angles[3*i+2], 00177 mol->angleTypeNames.name(mol->get_angletype(i))); 00178 } else { 00179 angle = Py_BuildValue("iii", mol->angles[3*i], mol->angles[3*i+1], 00180 mol->angles[3*i+2]); 00181 } 00182 PyList_SET_ITEM(returnlist, i, angle); 00183 if (PyErr_Occurred()) 00184 goto failure; 00185 } 00186 return returnlist; 00187 00188 failure: 00189 PyErr_SetString(PyExc_RuntimeError, "problem building angle list"); 00190 Py_XDECREF(returnlist); 00191 return NULL; 00192 } 00193 00194 00195 static const char dihed_doc[] = 00196 "Get all unique dihedrals within a specified molecule. Optionally, can get\n" 00197 "dihedral type as well\n\n" 00198 "Args:\n" 00199 " molid (int): Molecule ID to query. Defaults to top molecule\n" 00200 " type (bool): Whether to include dihedral type information in the result\n" 00201 " Defaults to False.\n" 00202 "Returns:\n" 00203 " (list of lists) Information about each dihedral in the system. Each\n" 00204 " dihedral will be a list with the indices of the four atoms\n" 00205 " comprising the dihedral, followed by dihedral type (as a string) if\n" 00206 " requested."; 00207 static PyObject* topo_get_dihed(PyObject *self, PyObject *args, 00208 PyObject *kwargs) { 00209 const char *kwlist[] = {"molid", "type", NULL}; 00210 PyObject *returnlist = NULL; 00211 int molid = -1, types = 0; 00212 Molecule *mol; 00213 int i; 00214 00215 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii:topology.dihedral", 00216 (char**) kwlist, &molid, &types)) 00217 return NULL; 00218 00219 VMDApp *app; 00220 if (!(app = get_vmdapp())) 00221 return NULL; 00222 00223 if (molid == -1) 00224 molid = app->molecule_top(); 00225 00226 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00227 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00228 return NULL; 00229 } 00230 00231 if (!(returnlist = PyList_New(mol->num_dihedrals()))) 00232 goto failure; 00233 00234 for (i = 0; i < mol->num_dihedrals(); i++) { 00235 PyObject* dihed; 00236 if (types) { 00237 dihed = Py_BuildValue("iiiis", 00238 mol->dihedrals[4*i], mol->dihedrals[4*i+1], 00239 mol->dihedrals[4*i+2], mol->dihedrals[4*i+3], 00240 mol->dihedralTypeNames.name(mol->get_dihedraltype(i))); 00241 } else { 00242 dihed = Py_BuildValue("iiii", 00243 mol->dihedrals[4*i], mol->dihedrals[4*i+1], 00244 mol->dihedrals[4*i+2], mol->dihedrals[4*i+3]); 00245 } 00246 PyList_SET_ITEM(returnlist, i, dihed); 00247 if (PyErr_Occurred()) 00248 goto failure; 00249 } 00250 return returnlist; 00251 00252 failure: 00253 PyErr_SetString(PyExc_RuntimeError, "Problem building dihedral list"); 00254 Py_XDECREF(returnlist); 00255 return NULL; 00256 } 00257 00258 00259 static const char impropers_doc[] = 00260 "Get all unique impropers within a specified molecule. Optionally, can get\n" 00261 "improper type as well\n\n" 00262 "Args:\n" 00263 " molid (int): Molecule ID to query. Defaults to top molecule\n" 00264 " type (bool): Whether to include improper type information in the result\n" 00265 " Defaults to False.\n" 00266 "Returns:\n" 00267 " (list of lists) Information about each improper in the system. Each\n" 00268 " improper will be a list with the indices of the four atoms\n" 00269 " comprising the improper, followed by improper type (as a string) if\n" 00270 " requested."; 00271 static PyObject* topo_get_impro(PyObject *self, PyObject *args, 00272 PyObject *kwargs) { 00273 const char *kwlist[] = {"molid", "type", NULL}; 00274 PyObject *returnlist = NULL; 00275 int molid = -1, types = 0; 00276 Molecule *mol; 00277 int i; 00278 00279 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii:topology.impropers", 00280 (char**) kwlist, &molid, &types)) 00281 return NULL; 00282 00283 VMDApp *app; 00284 if (!(app = get_vmdapp())) 00285 return NULL; 00286 00287 if (molid == -1) 00288 molid = app->molecule_top(); 00289 00290 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00291 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00292 return NULL; 00293 } 00294 00295 if (!(returnlist = PyList_New(mol->num_impropers()))) 00296 goto failure; 00297 00298 for (i = 0; i < mol->num_impropers(); i++) { 00299 PyObject* improper; 00300 if (types) { 00301 improper = Py_BuildValue("iiiis", 00302 mol->impropers[4*i], mol->impropers[4*i+1], 00303 mol->impropers[4*i+2], mol->impropers[4*i+3], 00304 mol->improperTypeNames.name(mol->get_impropertype(i))); 00305 } else { 00306 improper = Py_BuildValue("iiii", 00307 mol->impropers[4*i], mol->impropers[4*i+1], 00308 mol->impropers[4*i+2], mol->impropers[4*i+3]); 00309 } 00310 PyList_SetItem(returnlist, i, improper); 00311 } 00312 return returnlist; 00313 00314 failure: 00315 PyErr_SetString(PyExc_RuntimeError, "Problem building improper list"); 00316 Py_XDECREF(returnlist); 00317 return NULL; 00318 } 00319 00320 00321 static const char addbond_doc[] = 00322 "Add a bond between two atoms with given indices. If bond is already present,\n" 00323 "nothing will be done.\n\n" 00324 "Args:\n" 00325 " i (int): Index of first atom\n" 00326 " j (int): Index of second atom\n" 00327 " molid (int): Molecule ID to add bond to. Defaults to top molecule.\n" 00328 " order (float): Bond order. Defaults to 1.0\n" 00329 " type (str): Bond type. Can be from output of `topology.bondtypes()`,\n" 00330 " or can define a new bond type. Defaults to None"; 00331 static PyObject* topo_add_bond(PyObject *self, PyObject *args, PyObject *kwargs) { 00332 const char *kwlist[] = {"i", "j", "molid", "order", "type", NULL}; 00333 int molid = -1, type = -1; 00334 char *bondtype = NULL; 00335 float order = 1.0; 00336 Molecule *mol; 00337 int i, j; 00338 00339 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|ifz:topology.addbond", 00340 (char**) kwlist, &i, &j, &molid, &order, 00341 &bondtype)) 00342 return NULL; 00343 00344 VMDApp *app; 00345 if (!(app = get_vmdapp())) 00346 return NULL; 00347 00348 if (molid == -1) 00349 molid = app->molecule_top(); 00350 00351 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00352 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00353 return NULL; 00354 } 00355 00356 // Handle bond type 00357 if (bondtype) { 00358 type = mol->bondTypeNames.add_name(bondtype, 0); 00359 mol->set_dataset_flag(BaseMolecule::BONDTYPES); 00360 } 00361 00362 mol->set_dataset_flag(BaseMolecule::BONDS); 00363 mol->set_dataset_flag(BaseMolecule::BONDORDERS); 00364 00365 if (mol->add_bond_dupcheck(i, j, order, type)) { 00366 PyErr_Format(PyExc_RuntimeError, "Problem adding bond between atoms %d " 00367 "and %d on molid %d", i, j, molid); 00368 return NULL; 00369 } 00370 00371 Py_INCREF(Py_None); 00372 return Py_None; 00373 } 00374 00375 00376 static const char addangle_doc[] = 00377 "Add an angle between three atoms with given indices. No checking for\n" 00378 "duplicate angles is performed\n\n" 00379 "Args:\n" 00380 " i (int): Index of first atom\n" 00381 " j (int): Index of second atom\n" 00382 " k (int): Index of third atom\n" 00383 " molid (int): Molecule ID to add angle to. Defaults to top molecule.\n" 00384 " type (str): Angle type. Can be from output of `topology.getangletypes()`,\n" 00385 " or can define a new angle type. Defaults to None\n" 00386 "Returns:\n" 00387 " (int) Index of new angle in system"; 00388 static PyObject* topo_add_angle(PyObject *self, PyObject *args, 00389 PyObject *kwargs) { 00390 const char *kwlist[] = {"i", "j", "k", "molid", "type", NULL}; 00391 int molid = -1, type = -1; 00392 char *angletype = NULL; 00393 Molecule *mol; 00394 int i, j, k; 00395 00396 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iii|iz:topology.addangle", 00397 (char**) kwlist, &i, &j, &k, &molid, 00398 &angletype)) 00399 return NULL; 00400 00401 VMDApp *app; 00402 if (!(app = get_vmdapp())) 00403 return NULL; 00404 00405 if (molid == -1) 00406 molid = app->molecule_top(); 00407 00408 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00409 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00410 return NULL; 00411 } 00412 00413 if (angletype) { 00414 type = mol->angleTypeNames.add_name(angletype, 0); 00415 // This is indirectly set in add_angle, but do it explictly to be clear 00416 mol->set_dataset_flag(BaseMolecule::ANGLETYPES); 00417 } 00418 mol->set_dataset_flag(BaseMolecule::ANGLES); 00419 00420 return as_pyint(mol->add_angle(i, j, k, type)); 00421 } 00422 00423 00424 static const char adddihed_doc[] = 00425 "Add a dihedral between four atoms with the given indices. No checking for\n" 00426 "duplicate dihedrals is performed.\n\n" 00427 "Args:\n" 00428 " i (int): Index of first atom\n" 00429 " j (int): Index of second atom\n" 00430 " k (int): Index of third atom\n" 00431 " l (int): Index of fourth atom\n" 00432 " molid (int): Molecule ID to add dihedral in. Defaults to top molecule.\n" 00433 " type (str): Angle type. Can be from output of `topology.getangletypes()`,\n" 00434 " or can define a new angle type. Defaults to None\n" 00435 "Returns:\n" 00436 " (int) New number of dihedrals defined in system"; 00437 static PyObject* topo_add_dihed(PyObject *self, PyObject *args, 00438 PyObject *kwargs) { 00439 const char *kwlist[] = {"i", "j", "k", "l", "molid", "type", NULL}; 00440 int molid = -1, type = -1; 00441 char *dihetype = NULL; 00442 int i, j, k, l; 00443 Molecule *mol; 00444 00445 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iiii|iz:topology.adddihedral", 00446 (char**) kwlist, &i, &j, &k, &l, &molid, 00447 &dihetype)) 00448 return NULL; 00449 00450 VMDApp *app; 00451 if (!(app = get_vmdapp())) 00452 return NULL; 00453 00454 if (molid == -1) 00455 molid = app->molecule_top(); 00456 00457 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00458 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00459 return NULL; 00460 } 00461 00462 if (dihetype) { 00463 type = mol->dihedralTypeNames.add_name(dihetype, 0); 00464 // This is indirectly set in add_dihedral, but do it explictly to be clear 00465 // Yes, it is supposed to be the ANGLETYPES flag 00466 mol->set_dataset_flag(BaseMolecule::ANGLETYPES); 00467 } 00468 mol->set_dataset_flag(BaseMolecule::ANGLES); 00469 00470 return as_pyint(mol->add_dihedral(i, j, k, l, type)); 00471 } 00472 00473 00474 static const char addimproper_doc[] = 00475 "Add an improper dihedral between four atoms with the given indices. No\n" 00476 "checking for duplicate impropers is performed.\n\n" 00477 "Args:\n" 00478 " i (int): Index of first atom\n" 00479 " j (int): Index of second atom\n" 00480 " k (int): Index of third atom\n" 00481 " l (int): Index of fourth atom\n" 00482 " molid (int): Molecule ID to add dihedral in. Defaults to top molecule.\n" 00483 " type (str): Angle type. Can be from output of `topology.getangletypes()`,\n" 00484 " or can define a new angle type. Defaults to None\n" 00485 "Returns:\n" 00486 " (int) New number of improper dihedrals defined in system"; 00487 static PyObject* topo_add_improp(PyObject *self, PyObject *args, 00488 PyObject *kwargs) { 00489 const char *kwlist[] = {"i", "j", "k", "l", "molid", "type", NULL}; 00490 int molid = -1, type = -1; 00491 char *dihetype = NULL; 00492 int i, j, k, l; 00493 Molecule *mol; 00494 00495 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iiii|iz:topology.addimproper", 00496 (char**) kwlist, &i, &j, &k, &l, &molid, 00497 &dihetype)) 00498 return NULL; 00499 00500 VMDApp *app; 00501 if (!(app = get_vmdapp())) 00502 return NULL; 00503 00504 if (molid == -1) 00505 molid = app->molecule_top(); 00506 00507 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00508 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00509 return NULL; 00510 } 00511 00512 if (dihetype) { 00513 type = mol->improperTypeNames.add_name(dihetype, 0); 00514 // This is indirectly set in add_dihedral, but do it explictly to be clear 00515 // Yes, it is supposed to be the ANGLETYPES flag 00516 mol->set_dataset_flag(BaseMolecule::ANGLETYPES); 00517 } 00518 mol->set_dataset_flag(BaseMolecule::ANGLES); 00519 00520 return as_pyint(mol->add_improper(i, j, k, l, type)); 00521 } 00522 00523 00524 static const char delbond_doc[] = 00525 "Delete a bond between atoms with the given indices. If the bond does not\n" 00526 "exist, does nothing.\n\n" 00527 "Args:\n" 00528 " i (int): Index of first atom\n" 00529 " j (int): Index of second atom\n" 00530 " molid (int): Molecule ID to delete bond from. Defaults to top molecule.\n" 00531 "Returns:\n" 00532 " (bool) True if bond exists and was deleted"; 00533 static PyObject* topo_del_bond(PyObject *self, PyObject *args, PyObject *kwargs) { 00534 const char *kwlist[] = {"i", "j", "molid", NULL}; 00535 PyObject *result = Py_False; 00536 MolAtom *atomi, *atomj; 00537 float *bondOrders; 00538 int molid = -1; 00539 int *bondTypes; 00540 Molecule *mol; 00541 int i, j, tmp; 00542 00543 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i:topology.delbond", 00544 (char**) kwlist, &i, &j, &molid)) 00545 return NULL; 00546 00547 VMDApp *app; 00548 if (!(app = get_vmdapp())) 00549 return NULL; 00550 00551 if (molid == -1) 00552 molid = app->molecule_top(); 00553 00554 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00555 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00556 return NULL; 00557 } 00558 00559 if (i < 0 || j < 0 || i >= mol->nAtoms || j >= mol->nAtoms) { 00560 PyErr_Format(PyExc_ValueError, "invalid bond atom indices '%d'-'%d'", i, j); 00561 return NULL; 00562 } 00563 00564 bondOrders = mol->extraflt.data("bondorders"); 00565 bondTypes = mol->extraint.data("bondtypes"); 00566 atomi = mol->atom(i); 00567 atomj = mol->atom(j); 00568 00569 for (tmp = 0; tmp < atomi->bonds && j != atomi->bondTo[tmp]; tmp++); 00570 00571 // Match is found 00572 if (tmp < atomi->bonds) { 00573 atomi->bondTo[tmp] = atomi->bondTo[--atomi->bonds]; 00574 mol->set_dataset_flag(BaseMolecule::BONDS); 00575 00576 if (bondOrders) { 00577 bondOrders[i * MAXATOMBONDS + tmp] = bondOrders[i * MAXATOMBONDS + atomi->bonds]; 00578 bondOrders[i * MAXATOMBONDS + atomi->bonds] = 1.0; 00579 mol->set_dataset_flag(BaseMolecule::BONDORDERS); 00580 } 00581 00582 if (bondTypes) { 00583 bondTypes[i * MAXATOMBONDS + tmp] = bondTypes[i * MAXATOMBONDS + atomi->bonds]; 00584 bondTypes[i * MAXATOMBONDS + atomi->bonds] = -1; 00585 mol->set_dataset_flag(BaseMolecule::BONDTYPES); 00586 } 00587 00588 for (tmp = 0; tmp < atomj->bonds && i != atomj->bondTo[tmp]; tmp++); 00589 atomj->bondTo[tmp] = atomj->bondTo[--atomj->bonds]; 00590 00591 result = Py_True; 00592 } 00593 00594 Py_INCREF(result); 00595 return result; 00596 } 00597 00598 00599 static const char delangle_doc[] = 00600 "Delete an angle between atoms with the given indices. If the angle does not\n" 00601 "exist, does nothing.\n\n" 00602 "Args:\n" 00603 " i (int): Index of first atom\n" 00604 " j (int): Index of second atom\n" 00605 " k (int): Index of third atom\n" 00606 " molid (int): Molecule ID to delete from. Defaults to top molecule.\n" 00607 "Returns:\n" 00608 " (bool) True if angle exists and was deleted"; 00609 static PyObject* topo_del_angle(PyObject *self, PyObject *args, 00610 PyObject *kwargs) { 00611 const char *kwlist[] = {"i", "j", "k", "molid", NULL}; 00612 PyObject *result = Py_False; 00613 int molid = -1; 00614 int i, j, k, s; 00615 Molecule *mol; 00616 00617 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iii|i:topology:delangle", 00618 (char**) kwlist, &i, &j, &k, &molid)) 00619 return NULL; 00620 00621 VMDApp *app; 00622 if (!(app = get_vmdapp())) 00623 return NULL; 00624 00625 if (molid == -1) 00626 molid = app->molecule_top(); 00627 00628 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00629 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00630 return NULL; 00631 } 00632 00633 if (i < 0 || j < 0 || k < 0 || 00634 k >= mol->nAtoms || i >= mol->nAtoms || j >= mol->nAtoms) { 00635 PyErr_Format(PyExc_ValueError, "invalid angle atom indices %d-%d-%d", 00636 i, j, k); 00637 return NULL; 00638 } 00639 00640 // Reorder so i < k to follow convention for atom ordering in angles 00641 if (i > k) { 00642 s = k; 00643 k = i; 00644 i = s; 00645 } 00646 00647 s = mol->num_angles(); 00648 for (int tmp = 0; tmp < s; tmp++) { 00649 if (i == mol->angles[3*tmp ] && 00650 j == mol->angles[3*tmp+1] && 00651 k == mol->angles[3*tmp+2]) { 00652 mol->angles[3*tmp ] = mol->angles[3*s-3]; 00653 mol->angles[3*tmp+1] = mol->angles[3*s-2]; 00654 mol->angles[3*tmp+2] = mol->angles[3*s-1]; 00655 00656 if (mol->angleTypes.num() > tmp) { 00657 if (mol->angleTypes.num() == s) 00658 mol->angleTypes[tmp] = mol->angleTypes[s-1]; 00659 else 00660 mol->angleTypes[tmp] = -1; 00661 } 00662 00663 mol->angles.pop(); 00664 mol->angles.pop(); 00665 mol->angles.pop(); 00666 mol->set_dataset_flag(BaseMolecule::ANGLES); 00667 result = Py_True; 00668 break; 00669 } 00670 } 00671 00672 Py_INCREF(result); 00673 return result; 00674 } 00675 00676 00677 static const char deldihed_doc[] = 00678 "Delete a dihedral angle between atoms with the given indices. If the\n" 00679 "dihedral does not exist, does nothing.\n\n" 00680 "Args:\n" 00681 " i (int): Index of first atom\n" 00682 " j (int): Index of second atom\n" 00683 " k (int): Index of third atom\n" 00684 " l (int): Index of fourth atom\n" 00685 " molid (int): Molecule ID to delete from. Defaults to top molecule.\n" 00686 "Returns:\n" 00687 " (bool) True if dihedral exists and was deleted"; 00688 static PyObject* topo_del_dihed(PyObject *self, PyObject *args, 00689 PyObject *kwargs) { 00690 const char *kwlist[] = {"i", "j", "k", "l", "molid", NULL}; 00691 PyObject *result = Py_False; 00692 int i, j, k, l, tmp, s; 00693 int molid = -1; 00694 Molecule *mol; 00695 00696 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iiii|i:topology.deldihedral", 00697 (char**) kwlist, &i, &j, &k, &l, &molid)) 00698 return NULL; 00699 00700 VMDApp *app; 00701 if (!(app = get_vmdapp())) 00702 return NULL; 00703 00704 if (molid == -1) 00705 molid = app->molecule_top(); 00706 00707 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00708 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00709 return NULL; 00710 } 00711 00712 if (i < 0 || j < 0 || k < 0 || l < 0 || k >= mol->nAtoms || 00713 i >= mol->nAtoms || j >= mol->nAtoms || l >= mol->nAtoms) { 00714 PyErr_Format(PyExc_ValueError, "invalid dihedral atom indices %d-%d-%d-%d", 00715 i, j, k, l); 00716 return NULL; 00717 } 00718 00719 //Reorder so i < l as is convention for listing dihedrals 00720 if (i > l) { 00721 tmp = l; 00722 l = i; 00723 i = tmp; 00724 tmp = k; 00725 k = j; 00726 j = tmp; 00727 } 00728 00729 s = mol->num_dihedrals(); 00730 for (tmp = 0; tmp < s; tmp++) { 00731 if (i == mol->dihedrals[4*tmp] && j == mol->dihedrals[4*tmp+1] \ 00732 && k == mol->dihedrals[4*tmp+2] && l == mol->dihedrals[4*tmp+3]) { 00733 00734 mol->dihedrals[4*tmp] = mol->dihedrals[4*s-4]; 00735 mol->dihedrals[4*tmp+1] = mol->dihedrals[4*s-3]; 00736 mol->dihedrals[4*tmp+2] = mol->dihedrals[4*s-2]; 00737 mol->dihedrals[4*tmp+3] = mol->dihedrals[4*s-1]; 00738 if (mol->dihedralTypes.num() > tmp) { 00739 if (mol->dihedralTypes.num() == s) 00740 mol->dihedralTypes[tmp] = mol->dihedralTypes[s-1]; 00741 else 00742 mol->dihedralTypes[tmp] = -1; 00743 } 00744 mol->dihedrals.pop(); 00745 mol->dihedrals.pop(); 00746 mol->dihedrals.pop(); 00747 mol->dihedrals.pop(); 00748 mol->set_dataset_flag(BaseMolecule::ANGLES); 00749 00750 result = Py_True; 00751 break; 00752 } 00753 } 00754 00755 Py_INCREF(result); 00756 return result; 00757 } 00758 00759 00760 static const char delimproper_doc[] = 00761 "Delete an improper dihedral angle between atoms with the given indices. If\n" 00762 "the improper does not exist, does nothing.\n\n" 00763 "Args:\n" 00764 " i (int): Index of first atom\n" 00765 " j (int): Index of second atom\n" 00766 " k (int): Index of third atom\n" 00767 " l (int): Index of fourth atom\n" 00768 " molid (int): Molecule ID to delete from. Defaults to top molecule.\n" 00769 "Returns:\n" 00770 " (bool) True if improper dihedral exists and was deleted"; 00771 static PyObject* topo_del_improper(PyObject *self, PyObject *args, 00772 PyObject *kwargs) { 00773 const char *kwlist[] = {"i", "j", "k", "l", "molid", NULL}; 00774 PyObject *result = Py_False; 00775 int i, j, k, l, tmp, s; 00776 int molid = -1; 00777 Molecule *mol; 00778 00779 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iiii|i:topology.delimproper", 00780 (char**) kwlist, &i, &j, &k, &l, &molid)) 00781 return NULL; 00782 00783 VMDApp *app; 00784 if (!(app = get_vmdapp())) 00785 return NULL; 00786 00787 if (molid == -1) 00788 molid = app->molecule_top(); 00789 00790 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00791 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00792 return NULL; 00793 } 00794 00795 if (i < 0 || j < 0 || k < 0 || l < 0 || k >= mol->nAtoms || 00796 i >= mol->nAtoms || j >= mol->nAtoms || l >= mol->nAtoms) { 00797 PyErr_Format(PyExc_ValueError, "invalid imporper atom indices %d-%d-%d-%d", 00798 i, j, k, l); 00799 return NULL; 00800 } 00801 00802 //Reorder so i < l for convention with dihedral order 00803 if (i > l) { 00804 tmp = l; 00805 l = i; 00806 i = tmp; 00807 tmp = k; 00808 k = j; 00809 j = tmp; 00810 } 00811 00812 s = mol->num_impropers(); 00813 for (tmp = 0; tmp < s; tmp++) { 00814 if (i == mol->impropers[4*tmp ] && j == mol->impropers[4*tmp+1] && 00815 k == mol->impropers[4*tmp+2] && l == mol->impropers[4*tmp+3]) { 00816 00817 mol->impropers[4*tmp ] = mol->impropers[4*s-4]; 00818 mol->impropers[4*tmp+1] = mol->impropers[4*s-3]; 00819 mol->impropers[4*tmp+2] = mol->impropers[4*s-2]; 00820 mol->impropers[4*tmp+3] = mol->impropers[4*s-1]; 00821 00822 if (mol->improperTypes.num() > tmp) { 00823 if (mol->improperTypes.num() == s) 00824 mol->improperTypes[tmp] = mol->improperTypes[s-1]; 00825 else 00826 mol->improperTypes[tmp] = -1; 00827 } 00828 mol->impropers.pop(); 00829 mol->impropers.pop(); 00830 mol->impropers.pop(); 00831 mol->impropers.pop(); 00832 mol->set_dataset_flag(BaseMolecule::ANGLES); 00833 00834 result = Py_True; 00835 break; 00836 } 00837 } 00838 00839 Py_INCREF(result); 00840 return result; 00841 } 00842 00843 00844 static const char del_all_bond_doc[] = 00845 "Delete all bonds in a given molecule\n\n" 00846 "Args:\n" 00847 " molid (int): Molecule ID to delete bonds in. Defaults to top molecule.\n" 00848 "Returns:\n" 00849 " (int) Number of bonds deleted"; 00850 static PyObject* topo_del_all_bonds(PyObject *self, PyObject *args, 00851 PyObject *kwargs) { 00852 const char *kwlist[] = {"molid", NULL}; 00853 int molid = -1; 00854 Molecule *mol; 00855 00856 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:topology.delallbonds", 00857 (char**) kwlist, &molid)) 00858 return NULL; 00859 00860 VMDApp *app; 00861 if (!(app = get_vmdapp())) 00862 return NULL; 00863 00864 if (molid == -1) 00865 molid = app->molecule_top(); 00866 00867 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00868 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00869 return NULL; 00870 } 00871 00872 int retval = mol->count_bonds(); 00873 mol->clear_bonds(); 00874 00875 return as_pyint(retval); 00876 } 00877 00878 00879 static const char del_all_angle_doc[] = 00880 "Delete all angles in a given molecule\n\n" 00881 "Args:\n" 00882 " molid (int): Molecule ID to delete angles in. Defaults to top molecule.\n" 00883 "Returns:\n" 00884 " (int) Number of angles deleted"; 00885 static PyObject* topo_del_all_angles(PyObject *self, PyObject *args, 00886 PyObject *kwargs) { 00887 const char *kwlist[] = {"molid", NULL}; 00888 int molid = -1; 00889 Molecule *mol; 00890 00891 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:topology.delallangles", 00892 (char**) kwlist, &molid)) 00893 return NULL; 00894 00895 VMDApp *app; 00896 if (!(app = get_vmdapp())) 00897 return NULL; 00898 00899 if (molid == -1) 00900 molid = app->molecule_top(); 00901 00902 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00903 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00904 return NULL; 00905 } 00906 00907 int retval = mol->num_angles(); 00908 mol->angles.clear(); 00909 mol->angleTypes.clear(); 00910 00911 return as_pyint(retval); 00912 } 00913 00914 00915 static const char del_all_dihed_doc[] = 00916 "Delete all dihedrals in a given molecule\n\n" 00917 "Args:\n" 00918 " molid (int): Molecule ID to delete in. Defaults to top molecule\n" 00919 "Returns:\n" 00920 " (int) Number of dihedrals deleted"; 00921 static PyObject* topo_del_all_dihed(PyObject *self, PyObject *args, 00922 PyObject *kwargs) { 00923 const char *kwlist[] = {"molid", NULL}; 00924 int molid = -1; 00925 Molecule *mol; 00926 00927 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:topology.delalldihedrals", 00928 (char**) kwlist, &molid)) 00929 return NULL; 00930 00931 VMDApp *app; 00932 if (!(app = get_vmdapp())) 00933 return NULL; 00934 00935 if (molid == -1) 00936 molid = app->molecule_top(); 00937 00938 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00939 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00940 return NULL; 00941 } 00942 00943 int retval = mol->num_dihedrals(); 00944 mol->dihedrals.clear(); 00945 mol->dihedralTypes.clear(); 00946 00947 return as_pyint(retval); 00948 } 00949 00950 00951 static const char del_all_improper_doc[] = 00952 "Delete all improper dihedrals in a given molecule\n\n" 00953 "Args:\n" 00954 " molid (int): Molecule ID to delete in. Defaults to top molecule\n" 00955 "Returns:\n" 00956 " (int) Number of impropers deleted"; 00957 static PyObject* topo_del_all_impropers(PyObject *self, PyObject *args, 00958 PyObject *kwargs) { 00959 const char *kwlist[] = {"molid", NULL}; 00960 int molid = -1; 00961 Molecule *mol; 00962 00963 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:topology.delallimpropers", 00964 (char**) kwlist, &molid)) 00965 return NULL; 00966 00967 VMDApp *app; 00968 if (!(app = get_vmdapp())) 00969 return NULL; 00970 00971 if (molid == -1) 00972 molid = app->molecule_top(); 00973 00974 if (!(mol = app->moleculeList->mol_from_id(molid))) { 00975 PyErr_Format(PyExc_ValueError, "invalid molid '%d'", molid); 00976 return NULL; 00977 } 00978 00979 int retval = mol->num_impropers(); 00980 mol->impropers.clear(); 00981 mol->improperTypes.clear(); 00982 00983 return as_pyint(retval); 00984 } 00985 00986 00987 static const char btypes_doc[] = 00988 "Get all bond types defined in the molecule. If molecule does not have\n" 00989 "bond types, will return an empty list.\n\n" 00990 "Args:\n" 00991 " molid (int): Molecule ID to query. Defaults to top molecule\n" 00992 "Returns:\n" 00993 " (list of str): Bond types in molecule"; 00994 static PyObject* topo_bondtypes(PyObject *self, PyObject *args, 00995 PyObject *kwargs) { 00996 const char *kwlist[] = {"molid", NULL}; 00997 PyObject *returnlist = NULL; 00998 int molid = -1; 00999 Molecule *mol; 01000 int i; 01001 01002 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:topology.bondtypes", 01003 (char**) kwlist, &molid)) 01004 return NULL; 01005 01006 VMDApp *app; 01007 if (!(app = get_vmdapp())) 01008 return NULL; 01009 01010 if (molid == -1) 01011 molid = app->molecule_top(); 01012 01013 if (!(mol = app->moleculeList->mol_from_id(molid))) { 01014 PyErr_Format(PyExc_ValueError, "Invalid molecule id '%d'", molid); 01015 return NULL; 01016 } 01017 01018 if (!(returnlist = PyList_New(mol->bondTypeNames.num()))) 01019 goto failure; 01020 01021 for (i = 0; i < mol->bondTypeNames.num(); i++) { 01022 PyList_SET_ITEM(returnlist, i, as_pystring(mol->bondTypeNames.name(i))); 01023 if (PyErr_Occurred()) 01024 goto failure; 01025 } 01026 01027 return returnlist; 01028 01029 failure: 01030 PyErr_Format(PyExc_RuntimeError, "Problem building bond type list for molid " 01031 "%d", molid); 01032 Py_XDECREF(returnlist); 01033 return NULL; 01034 } 01035 01036 01037 static const char atypes_doc[] = 01038 "Get all angle types defined in the molecule. If molecule does not have angle\n" 01039 "types, will return an empty list.\n\n" 01040 "Args:\n" 01041 " molid (int): Molecule ID to query. Defaults to top molecule\n" 01042 "Returns:\n" 01043 " (list of str): Angle types in molecule"; 01044 static PyObject* topo_angletypes(PyObject *self, PyObject *args, 01045 PyObject *kwargs) { 01046 const char *kwlist[] = {"molid", NULL}; 01047 PyObject *returnlist = NULL; 01048 int molid = -1; 01049 Molecule *mol; 01050 int i; 01051 01052 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:topology.angletypes", 01053 (char**) kwlist, &molid)) 01054 return NULL; 01055 01056 VMDApp *app; 01057 if (!(app = get_vmdapp())) 01058 return NULL; 01059 01060 if (molid == -1) 01061 molid = app->molecule_top(); 01062 01063 if (!(mol = app->moleculeList->mol_from_id(molid))) { 01064 PyErr_Format(PyExc_ValueError, "Invalid molecule id '%d'", molid); 01065 return NULL; 01066 } 01067 01068 if (!(returnlist = PyList_New(mol->angleTypeNames.num()))) 01069 goto failure; 01070 01071 for (i = 0; i < mol->angleTypeNames.num(); i++) { 01072 PyList_SET_ITEM(returnlist, i, as_pystring(mol->angleTypeNames.name(i))); 01073 if (PyErr_Occurred()) 01074 goto failure; 01075 } 01076 01077 return returnlist; 01078 01079 failure: 01080 PyErr_Format(PyExc_RuntimeError, "Problem building angle type list for molid " 01081 "%d", molid); 01082 Py_XDECREF(returnlist); 01083 return NULL; 01084 } 01085 01086 01087 static const char dtypes_doc[] = 01088 "Get all dihedral types defined in the molecule. If the molecule does not\n" 01089 "have dihedral types, will return an empty list.\n\n" 01090 "Args:\n" 01091 " molid (int): Molecule ID to query. Defaults to top molecule\n" 01092 "Returns:\n" 01093 " (list of str): Dihedral types in molecule"; 01094 static PyObject* topo_dihetypes(PyObject *self, PyObject *args, 01095 PyObject *kwargs) { 01096 const char *kwlist[] = {"molid", NULL}; 01097 PyObject *returnlist = NULL; 01098 int molid = -1; 01099 Molecule *mol; 01100 int i; 01101 01102 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:topology.dihedraltypes", 01103 (char**) kwlist, &molid)) 01104 return NULL; 01105 01106 VMDApp *app; 01107 if (!(app = get_vmdapp())) 01108 return NULL; 01109 01110 if (molid == -1) 01111 molid = app->molecule_top(); 01112 01113 if (!(mol = app->moleculeList->mol_from_id(molid))) { 01114 PyErr_Format(PyExc_ValueError, "Invalid molecule id '%d'", molid); 01115 return NULL; 01116 } 01117 01118 if (!(returnlist = PyList_New(mol->dihedralTypeNames.num()))) 01119 goto failure; 01120 01121 for (i = 0; i < mol->dihedralTypeNames.num(); i++) { 01122 PyList_SET_ITEM(returnlist, i, as_pystring(mol->dihedralTypeNames.name(i))); 01123 if (PyErr_Occurred()) 01124 goto failure; 01125 } 01126 01127 return returnlist; 01128 01129 failure: 01130 PyErr_Format(PyExc_RuntimeError, "Problem building dihedral type list for " 01131 "molid %d", molid); 01132 Py_XDECREF(returnlist); 01133 return NULL; 01134 } 01135 01136 01137 static const char itypes_doc[] = 01138 "Get all improper dihedral types defined in the molecule. If the molecule\n" 01139 "not have improper types, will return an empty list.\n\n" 01140 "Args:\n" 01141 " molid (int): Molecule ID to query. Defaults to top molecule\n" 01142 "Returns:\n" 01143 " (list of str): Improper dihedral types in molecule"; 01144 static PyObject* topo_imptypes(PyObject *self, PyObject *args, PyObject *kwargs) { 01145 const char *kwlist[] = {"molid", NULL}; 01146 PyObject *returnlist = NULL; 01147 int molid = -1; 01148 Molecule *mol; 01149 int i; 01150 01151 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:topology.impropertypes", 01152 (char**) kwlist, &molid)) 01153 return NULL; 01154 01155 VMDApp *app; 01156 if (!(app = get_vmdapp())) 01157 return NULL; 01158 01159 if (molid == -1) 01160 molid = app->molecule_top(); 01161 01162 if (!(mol = app->moleculeList->mol_from_id(molid))) { 01163 PyErr_Format(PyExc_ValueError, "Invalid molecule id '%d'", molid); 01164 return NULL; 01165 } 01166 01167 if (!(returnlist = PyList_New(mol->improperTypeNames.num()))) 01168 goto failure; 01169 01170 for (i = 0; i < mol->improperTypeNames.num(); i++) { 01171 PyList_SET_ITEM(returnlist, i, as_pystring(mol->improperTypeNames.name(i))); 01172 if (PyErr_Occurred()) 01173 goto failure; 01174 } 01175 01176 return returnlist; 01177 01178 failure: 01179 PyErr_Format(PyExc_RuntimeError, "Problem building improper dihedral type " 01180 "list for molid %d", molid); 01181 Py_XDECREF(returnlist); 01182 return NULL; 01183 } 01184 01185 01186 static PyMethodDef methods[] = { 01187 {"bonds", (PyCFunction)topo_get_bond, METH_VARARGS | METH_KEYWORDS, bond_doc}, 01188 {"angles", (PyCFunction)topo_get_angle, METH_VARARGS | METH_KEYWORDS, angle_doc}, 01189 {"dihedrals", (PyCFunction)topo_get_dihed, METH_VARARGS | METH_KEYWORDS, dihed_doc}, 01190 {"impropers", (PyCFunction)topo_get_impro, METH_VARARGS | METH_KEYWORDS, impropers_doc}, 01191 {"addbond", (PyCFunction)topo_add_bond, METH_VARARGS | METH_KEYWORDS, addbond_doc}, 01192 {"addangle", (PyCFunction)topo_add_angle, METH_VARARGS | METH_KEYWORDS, addangle_doc}, 01193 {"adddihedral", (PyCFunction)topo_add_dihed, METH_VARARGS | METH_KEYWORDS, adddihed_doc}, 01194 {"addimproper", (PyCFunction)topo_add_improp, METH_VARARGS | METH_KEYWORDS, addimproper_doc}, 01195 {"delbond", (PyCFunction)topo_del_bond, METH_VARARGS | METH_KEYWORDS, delbond_doc}, 01196 {"delangle", (PyCFunction)topo_del_angle, METH_VARARGS | METH_KEYWORDS, delangle_doc}, 01197 {"deldihedral", (PyCFunction)topo_del_dihed, METH_VARARGS | METH_KEYWORDS, deldihed_doc}, 01198 {"delimproper", (PyCFunction)topo_del_improper, METH_VARARGS | METH_KEYWORDS, delimproper_doc}, 01199 {"delallbonds", (PyCFunction)topo_del_all_bonds, METH_VARARGS | METH_KEYWORDS, del_all_bond_doc}, 01200 {"delallangles", (PyCFunction)topo_del_all_angles, METH_VARARGS | METH_KEYWORDS, del_all_angle_doc}, 01201 {"delalldihedrals", (PyCFunction)topo_del_all_dihed, METH_VARARGS | METH_KEYWORDS, del_all_dihed_doc}, 01202 {"delallimpropers", (PyCFunction)topo_del_all_impropers, METH_VARARGS | METH_KEYWORDS, del_all_improper_doc}, 01203 {"bondtypes", (PyCFunction)topo_bondtypes, METH_VARARGS | METH_KEYWORDS, btypes_doc}, 01204 {"angletypes", (PyCFunction)topo_angletypes, METH_VARARGS | METH_KEYWORDS, atypes_doc}, 01205 {"dihedraltypes", (PyCFunction)topo_dihetypes, METH_VARARGS | METH_KEYWORDS, dtypes_doc}, 01206 {"impropertypes", (PyCFunction)topo_imptypes, METH_VARARGS | METH_KEYWORDS, itypes_doc}, 01207 {NULL, NULL} 01208 }; 01209 01210 01211 static const char topo_moddoc[] = 01212 "Methods for querying or modifying the topology of a molecule, which consists " 01213 "of all defined bonds, angles, dihedrals, and impropers, for applicable " 01214 "topology file formats."; 01215 01216 01217 #if PY_MAJOR_VERSION >= 3 01218 static struct PyModuleDef topologydef = { 01219 PyModuleDef_HEAD_INIT, 01220 "topology", 01221 topo_moddoc, 01222 -1, 01223 methods, 01224 }; 01225 #endif 01226 01227 01228 PyObject* inittopology(void) { 01229 #if PY_MAJOR_VERSION >= 3 01230 PyObject *m = PyModule_Create(&topologydef); 01231 #else 01232 PyObject *m = Py_InitModule3("topology", methods, topo_moddoc); 01233 #endif 01234 01235 return m; 01236 } 01237 01238