static PyObject *setbonds(PyObject *self, PyObject *args) { int molid; PyObject *atomlist, *bondlist; if (!PyArg_ParseTuple(args, (char *)"iO!O!:setbonds", &molid, &PyTuple_Type, &atomlist, &PyList_Type, &bondlist)) return NULL; // bad args Molecule *mol = get_vmdapp()->moleculeList->mol_from_id(molid); if (!mol) { PyErr_SetString(PyExc_ValueError, "molecule no longer exists"); return NULL; } int num_atoms = mol->nAtoms; int num_selected = PyTuple_Size(atomlist); if (PyList_Size(bondlist) != num_selected) { PyErr_SetString(PyExc_ValueError, (char *)"setbonds: atomlist and bondlist must have the same size"); return NULL; } mol->force_recalc(DrawMolItem::MOL_REGEN); // many reps ignore bonds for (int i=0; i<num_selected; i++) { int id = PyInt_AsLong(PyTuple_GET_ITEM(atomlist, i)); if (PyErr_Occurred()) { return NULL; } if (id < 0 || id >= num_atoms) { PyErr_SetString(PyExc_ValueError, (char *)"invalid atom id found"); return NULL; } MolAtom *atom = mol->atom(id); PyObject *atomids = PyList_GET_ITEM(bondlist, i); if (!PyList_Check(atomids)) { PyErr_SetString(PyExc_TypeError, (char *)"bondlist must contain lists"); return NULL; } int numbonds = PyList_Size(atomids); int k=0; for (int j=0; j<numbonds; j++) { int bond = PyInt_AsLong(PyList_GET_ITEM(atomids, j)); if (PyErr_Occurred()) return NULL; if (bond >= 0 && bond < mol->nAtoms) { atom->bondTo[k++] = bond; } else { char buf[40]; sprintf(buf, "Invalid atom id in bondlist: %d", bond); PyErr_SetString(PyExc_ValueError, buf); return NULL; } } atom->bonds = k; } Py_INCREF(Py_None); return Py_None; }
static PyObject *py_align(PyObject *self, PyObject *args) { int selmol, selframe, refmol, refframe, movemol, moveframe; PyObject *selobj, *refobj, *moveobj, *weightobj = NULL; if (!PyArg_ParseTuple(args, (char *)"iiO!iiO!iiO!O:atomselection.align", &selmol, &selframe, &PyTuple_Type, &selobj, &refmol, &refframe, &PyTuple_Type, &refobj, &movemol, &moveframe, &PyTuple_Type, &moveobj, &weightobj)) return NULL; // check if movemol is -1. If so, use the sel molecule and timestep instead if (movemol == -1) { movemol = selmol; moveobj = NULL; } VMDApp *app = get_vmdapp(); AtomSel *sel=NULL, *ref=NULL, *move=NULL; if (!(sel = sel_from_py(selmol, selframe, selobj, app)) || !(ref = sel_from_py(refmol, refframe, refobj, app)) || !(move = sel_from_py(movemol, moveframe, moveobj, app))) { delete sel; delete ref; delete move; return NULL; } const float *selts, *refts; float *movets; if (!(selts = sel->coordinates(app->moleculeList)) || !(refts = ref->coordinates(app->moleculeList)) || !(movets = move->coordinates(app->moleculeList))) { delete sel; delete ref; delete move; PyErr_SetString(PyExc_ValueError, "No coordinates in selection"); return NULL; } float *weight = parse_weight(sel, weightobj); if (!weight) { delete sel; delete ref; delete move; return NULL; } // Find the matrix that aligns sel with ref. Apply the transformation to // the atoms in move. // XXX need to add support for the "order" parameter as in Tcl. Matrix4 mat; int rc = measure_fit(sel, ref, selts, refts, weight, NULL, &mat); delete [] weight; delete sel; delete ref; if (rc < 0) { delete move; PyErr_SetString(PyExc_ValueError, (char *)measure_error(rc)); return NULL; } for (int i=0; i<move->num_atoms; i++) { if (move->on[i]) { float *pos = movets+3*i; mat.multpoint3d(pos, pos); } } Molecule *mol = app->moleculeList->mol_from_id(move->molid()); mol->force_recalc(DrawMolItem::MOL_REGEN); delete move; Py_INCREF(Py_None); return Py_None; }
static PyObject *set(PyObject *self, PyObject *args) { int i, molid, frame; PyObject *selected, *val; char *attr = 0; // // get molid, frame, list, attribute, and value // if (!PyArg_ParseTuple(args, (char *)"iiO!sO!", &molid, &frame, &PyTuple_Type, &selected, &attr, &PyTuple_Type, &val )) return NULL; // bad args // // check that we have been given either one value or one for each selected // atom // int num_selected = PyTuple_Size(selected); int tuplesize = PyTuple_Size(val); if (tuplesize != 1 && tuplesize != num_selected) { PyErr_SetString(PyExc_ValueError, "wrong number of items"); return NULL; } // // check molecule // VMDApp *app = get_vmdapp(); Molecule *mol = app->moleculeList->mol_from_id(molid); if (!mol) { PyErr_SetString(PyExc_ValueError, "molecule no longer exists"); return NULL; } const int num_atoms = mol->nAtoms; // // Check for a valid attribute // SymbolTable *table = app->atomSelParser; int attrib_index = table->find_attribute(attr); if (attrib_index == -1) { PyErr_SetString(PyExc_ValueError, "unknown atom attribute"); return NULL; } SymbolTableElement *elem = table->fctns.data(attrib_index); if (elem->is_a != SymbolTableElement::KEYWORD && elem->is_a != SymbolTableElement::SINGLEWORD) { PyErr_SetString(PyExc_ValueError, "attribute is not a keyword or singleword"); return NULL; } if (!table->is_changeable(attrib_index)) { PyErr_SetString(PyExc_ValueError, "attribute is not modifiable"); return NULL; } // // convert the list of selected atoms into an array of integer flags // // XXX should check that selected contains valid indices int *flgs = new int[num_atoms]; memset(flgs,0,num_atoms*sizeof(int)); for (i=0; i<num_selected; i++) flgs[PyInt_AsLong(PyTuple_GET_ITEM(selected,i))] = 1; // // set the data // // singlewords can never be set, so macro is NULL. atomsel_ctxt context(table, mol, frame, NULL); if (elem->returns_a == SymbolTableElement::IS_INT) { int *list = new int[num_atoms]; if (tuplesize > 1) { int j=0; for (int i=0; i<num_atoms; i++) { if (flgs[i]) list[i] = PyInt_AsLong(PyTuple_GET_ITEM(val, j++)); } } else { for (int i=0; i<num_atoms; i++) { if (flgs[i]) list[i] = PyInt_AsLong(PyTuple_GET_ITEM(val, 0)); } } elem->set_keyword_int(&context, num_atoms, list, flgs); delete [] list; } else if (elem->returns_a == SymbolTableElement::IS_FLOAT) { double *list = new double[num_atoms]; if (tuplesize > 1) { int j=0; for (int i=0; i<num_atoms; i++) { if (flgs[i]) list[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(val, j++)); } } else { for (int i=0; i<num_atoms; i++) { if (flgs[i]) list[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(val, 0)); } } elem->set_keyword_double(&context, num_atoms, list, flgs); delete [] list; } else if (elem->returns_a == SymbolTableElement::IS_STRING) { const char **list = new const char *[num_atoms]; if (tuplesize > 1) { int j=0; for (int i=0; i<num_atoms; i++) { if (flgs[i]) list[i] = PyString_AsString(PyTuple_GET_ITEM(val, j++)); } } else { for (int i=0; i<num_atoms; i++) { if (flgs[i]) list[i] = PyString_AsString(PyTuple_GET_ITEM(val, 0)); } } elem->set_keyword_string(&context, num_atoms, list, flgs); delete [] list; } // Recompute the color assignments if certain atom attributes are changed. if (!strcmp(attr, "name") || !strcmp(attr, "type") || !strcmp(attr, "resname") || !strcmp(attr, "chain") || !strcmp(attr, "segid") || !strcmp(attr, "segname")) app->moleculeList->add_color_names(molid); mol->force_recalc(DrawMolItem::SEL_REGEN | DrawMolItem::COL_REGEN); delete [] flgs; Py_INCREF(Py_None); return Py_None; }