00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdlib.h>
00024 #include <tcl.h>
00025 #include <ctype.h>
00026 #include "TclCommands.h"
00027 #include "AtomSel.h"
00028 #include "Matrix4.h"
00029 #include "SymbolTable.h"
00030 #include "VMDApp.h"
00031 #include "MoleculeList.h"
00032 #include "utilities.h"
00033 #include "config.h"
00034 #include "Measure.h"
00035 #include "MeasureSymmetry.h"
00036 #include "SpatialSearch.h"
00037 #include "Atom.h"
00038 #include "Molecule.h"
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 int tcl_get_weights(Tcl_Interp *interp, VMDApp *app, AtomSel *sel,
00058 Tcl_Obj *weight_obj, float *data) {
00059
00060 char *weight_string = NULL;
00061 if (!sel) return MEASURE_ERR_NOSEL;
00062 if (!app->molecule_valid_id(sel->molid())) return MEASURE_ERR_NOMOLECULE;
00063 if (weight_obj)
00064 weight_string = Tcl_GetStringFromObj(weight_obj, NULL);
00065
00066 if (!weight_string || !strcmp(weight_string, "none")) {
00067 for (int i=0; i<sel->selected; i++) {
00068 data[i] = 1.0;
00069 }
00070 return 0;
00071 }
00072
00073 SymbolTable *atomSelParser = app->atomSelParser;
00074
00075
00076 atomsel_ctxt context(atomSelParser,
00077 app->moleculeList->mol_from_id(sel->molid()),
00078 sel->which_frame, NULL);
00079
00080 int fctn = atomSelParser->find_attribute(weight_string);
00081 if (fctn >= 0) {
00082
00083
00084
00085 if (atomSelParser->fctns.data(fctn)->returns_a != SymbolTableElement::IS_FLOAT) {
00086 Tcl_AppendResult(interp,
00087 "weight attribute must have floating point values", NULL);
00088 return MEASURE_ERR_BADWEIGHTPARM;
00089 }
00090 double *tmp_data = new double[sel->num_atoms];
00091 atomSelParser->fctns.data(fctn)->keyword_double(
00092 &context, sel->num_atoms,tmp_data, sel->on);
00093 int j=0;
00094 for (int i=0; i<sel->num_atoms; i++) {
00095 if (sel->on[i])
00096 data[j++] = (float)tmp_data[i];
00097 }
00098 delete [] tmp_data;
00099 return 0;
00100 }
00101
00102 int list_num;
00103 Tcl_Obj **list_data;
00104 if (Tcl_ListObjGetElements(interp, weight_obj, &list_num, &list_data)
00105 != TCL_OK) {
00106 return MEASURE_ERR_BADWEIGHTPARM;
00107 }
00108 if (list_num != sel->selected && list_num != sel->num_atoms)
00109 return MEASURE_ERR_BADWEIGHTNUM;
00110
00111 int j = 0;
00112 for (int i=0; i<list_num; i++) {
00113 double tmp_data;
00114 if (Tcl_GetDoubleFromObj(interp, list_data[i], &tmp_data) != TCL_OK)
00115 return MEASURE_ERR_NONNUMBERPARM;
00116 if (list_num == sel->selected) {
00117
00118 data[i] = (float)tmp_data;
00119 } else {
00120 if (sel->on[i]) {
00121
00122 data[j++] = (float)tmp_data;
00123 }
00124 }
00125 }
00126 return 0;
00127 }
00128
00129
00130 int tcl_get_orders(Tcl_Interp *interp, int selnum,
00131 Tcl_Obj *order_obj, int *data) {
00132 int list_num;
00133 Tcl_Obj **list_data;
00134
00135 if (Tcl_ListObjGetElements(interp, order_obj, &list_num, &list_data)
00136 != TCL_OK) {
00137 return MEASURE_ERR_NOSEL;
00138 }
00139
00140
00141 if (list_num != selnum) return MEASURE_ERR_NOSEL;
00142
00143 for (int i=0; i<list_num; i++) {
00144 if (Tcl_GetIntFromObj(interp, list_data[i], &data[i]) != TCL_OK)
00145 return MEASURE_ERR_NONNUMBERPARM;
00146
00147
00148 if (data[i] < 0 || data[i] >= selnum)
00149 return MEASURE_ERR_BADORDERINDEX;
00150 }
00151
00152 return 0;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 static int vmd_measure_center(VMDApp *app, int argc, Tcl_Obj *const objv[], Tcl_Interp *interp)
00174 {
00175 if (argc != 2 && argc != 4 ) {
00176 Tcl_WrongNumArgs(interp, 2, objv-1,
00177 (char *)"<sel> [weight <weights>]");
00178 return TCL_ERROR;
00179 }
00180 if (argc == 4 && strcmp(Tcl_GetStringFromObj(objv[2],NULL), "weight")) {
00181 Tcl_SetResult(interp, (char *) "measure center: parameter can only be 'weight'", TCL_STATIC);
00182 return TCL_ERROR;
00183 }
00184
00185
00186 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
00187 if (!sel) {
00188 Tcl_SetResult(interp, (char *) "measure center: no atom selection", TCL_STATIC);
00189 return TCL_ERROR;
00190 }
00191
00192
00193 float *weight = new float[sel->selected];
00194 {
00195 int ret_val;
00196 if (argc == 2) {
00197 ret_val = tcl_get_weights(interp, app, sel, NULL, weight);
00198 } else {
00199 ret_val = tcl_get_weights(interp, app, sel, objv[3], weight);
00200 }
00201 if (ret_val < 0) {
00202 Tcl_AppendResult(interp, "measure center: ", measure_error(ret_val),
00203 NULL);
00204 delete [] weight;
00205 return TCL_ERROR;
00206 }
00207 }
00208
00209
00210 {
00211 float com[3];
00212 const float *framepos = sel->coordinates(app->moleculeList);
00213 int ret_val = measure_center(sel, framepos, weight, com);
00214 delete [] weight;
00215 if (ret_val < 0) {
00216 Tcl_AppendResult(interp, "measure center: ", measure_error(ret_val),
00217 NULL);
00218 return TCL_ERROR;
00219 }
00220 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00221 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(com[0]));
00222 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(com[1]));
00223 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(com[2]));
00224 Tcl_SetObjResult(interp, tcl_result);
00225 }
00226
00227 return TCL_OK;
00228 }
00229
00230
00231
00232 static int vmd_measure_sumweights(VMDApp *app, int argc, Tcl_Obj *const objv[], Tcl_Interp *interp) {
00233 if (argc != 4) {
00234 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<sel> weight <weights>");
00235 return TCL_ERROR;
00236 }
00237 if (strcmp(Tcl_GetStringFromObj(objv[2],NULL), "weight")) {
00238 Tcl_SetResult(interp, (char *) "measure sumweights: parameter can only be 'weight'", TCL_STATIC);
00239 return TCL_ERROR;
00240 }
00241
00242
00243 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL)
00244 );
00245 if (!sel) {
00246 Tcl_SetResult(interp, (char *) "measure sumweights: no atom selection", TCL_STATIC);
00247 return TCL_ERROR;
00248 }
00249
00250
00251 float *weight = new float[sel->selected];
00252 {
00253 int ret_val = tcl_get_weights(interp, app, sel, objv[3], weight);
00254 if (ret_val < 0) {
00255 Tcl_AppendResult(interp, "measure center: ", measure_error(ret_val),
00256 NULL);
00257 delete [] weight;
00258 return TCL_ERROR;
00259 }
00260 }
00261
00262
00263 {
00264 float weightsum;
00265 int ret_val = measure_sumweights(sel, sel->selected, weight, &weightsum);
00266 delete [] weight;
00267 if (ret_val < 0) {
00268 Tcl_AppendResult(interp, "measure center: ", measure_error(ret_val),
00269 NULL);
00270 return TCL_ERROR;
00271 }
00272 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00273 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(weightsum));
00274 Tcl_SetObjResult(interp, tcl_result);
00275 }
00276
00277 return TCL_OK;
00278 }
00279
00280
00281
00282
00283
00284 static int vmd_measure_avpos(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00285 int first = 0;
00286 int last = -1;
00287 int step = 1;
00288
00289 if (argc < 2 || argc > 8) {
00290 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> [first <first>] [last <last>] [step <step>]");
00291 return TCL_ERROR;
00292 }
00293 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL)
00294 );
00295 if (!sel) {
00296 Tcl_AppendResult(interp, "measure avpos: no atom selection", NULL);
00297 return TCL_ERROR;
00298 }
00299
00300 int i;
00301 for (i=2; i<argc; i+=2) {
00302 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00303 if (!strupncmp(argvcur, "first", CMDLEN)) {
00304 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00305 Tcl_AppendResult(interp, "measure avpos: bad first frame value", NULL);
00306 return TCL_ERROR;
00307 }
00308 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00309 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00310 Tcl_AppendResult(interp, "measure avpos: bad last frame value", NULL);
00311 return TCL_ERROR;
00312 }
00313 } else if (!strupncmp(argvcur, "step", CMDLEN)) {
00314 if (Tcl_GetIntFromObj(interp, objv[i+1], &step) != TCL_OK) {
00315 Tcl_AppendResult(interp, "measure avpos: bad frame step value", NULL);
00316 return TCL_ERROR;
00317 }
00318 } else {
00319 Tcl_AppendResult(interp, "measure avpos: invalid syntax, no such keyword: ", argvcur, NULL);
00320 return TCL_ERROR;
00321 }
00322 }
00323
00324 float *avpos = new float[3*sel->selected];
00325 int ret_val = measure_avpos(sel, app->moleculeList, first, last, step, avpos);
00326 if (ret_val < 0) {
00327 Tcl_AppendResult(interp, "measure avpos: ", measure_error(ret_val), NULL);
00328 delete [] avpos;
00329 return TCL_ERROR;
00330 }
00331
00332 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00333 for (i=0; i<sel->selected; i++) {
00334 Tcl_Obj *atom = Tcl_NewListObj(0, NULL);
00335 Tcl_ListObjAppendElement(interp, atom, Tcl_NewDoubleObj(avpos[i*3 ]));
00336 Tcl_ListObjAppendElement(interp, atom, Tcl_NewDoubleObj(avpos[i*3 + 1]));
00337 Tcl_ListObjAppendElement(interp, atom, Tcl_NewDoubleObj(avpos[i*3 + 2]));
00338 Tcl_ListObjAppendElement(interp, tcl_result, atom);
00339 }
00340
00341 Tcl_SetObjResult(interp, tcl_result);
00342
00343 delete [] avpos;
00344
00345 return TCL_OK;
00346 }
00347
00348
00349
00350
00351 static int vmd_measure_dipole(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00352 const char *opt;
00353 int unitsdebye=0;
00354 int usecenter=1;
00355
00356
00357 if ((argc < 2) || (argc > 4)) {
00358 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> [-elementary|-debye] [-geocenter|-masscenter|-origincenter]");
00359 return TCL_ERROR;
00360 }
00361 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1], NULL)
00362 );
00363 if (!sel) {
00364 Tcl_AppendResult(interp, "measure dipole: no atom selection", NULL);
00365 return TCL_ERROR;
00366 }
00367
00368 int i;
00369 for (i=0; i < (argc-2); ++i) {
00370 opt = Tcl_GetStringFromObj(objv[2+i], NULL);
00371 if (!strcmp(opt, "-debye"))
00372 unitsdebye=1;
00373 if (!strcmp(opt, "-elementary"))
00374 unitsdebye=0;
00375
00376 if (!strcmp(opt, "-geocenter"))
00377 usecenter=1;
00378 if (!strcmp(opt, "-masscenter"))
00379 usecenter=-1;
00380 if (!strcmp(opt, "-origincenter"))
00381 usecenter=0;
00382 }
00383
00384 float dipole[3];
00385 int ret_val = measure_dipole(sel, app->moleculeList, dipole, unitsdebye, usecenter);
00386 if (ret_val < 0) {
00387 Tcl_AppendResult(interp, "measure dipole: ", measure_error(ret_val), NULL);
00388 return TCL_ERROR;
00389 }
00390
00391 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00392 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(dipole[0]));
00393 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(dipole[1]));
00394 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(dipole[2]));
00395 Tcl_SetObjResult(interp, tcl_result);
00396
00397 return TCL_OK;
00398 }
00399
00400
00401
00402
00403
00404
00405 static int vmd_measure_dihed(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00406 int first=-1, last=-1, frame=-1;
00407
00408 if(argc<2) {
00409 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "{{<atomid1> [<molid1>]} {<atomid2> [<molid2>]} {<atomid3> [<molid3>]} {<atomid4> [<molid4>]}} [molid <default molid>] [frame <frame|all|last> | first <first> last <last>]");
00410 return TCL_ERROR;
00411 }
00412
00413 int molid[4];
00414 int atmid[4];
00415 int defmolid = -1;
00416 bool allframes = false;
00417
00418
00419 char *geomname = Tcl_GetStringFromObj(objv[0],NULL);
00420
00421
00422
00423 int numatms;
00424 Tcl_Obj **data;
00425 if (Tcl_ListObjGetElements(interp, objv[1], &numatms, &data) != TCL_OK) {
00426 Tcl_AppendResult(interp, " measure ", geomname, ": bad syntax", NULL);
00427 Tcl_AppendResult(interp, " Usage: measure ", geomname, " {{<atomid1> [<molid1>]} {<atomid2> [<molid2>]} {<atomid3> [<molid3>]} {<atomid4> [<molid4>]}} [molid <default molid>] [frame <frame|all|last> | first <first> last <last>]", NULL);
00428
00429 return TCL_ERROR;
00430 }
00431
00432 if (numatms!=4) {
00433 Tcl_AppendResult(interp, " measure dihed: must specify exactly four atoms in a list", NULL);
00434 return TCL_ERROR;
00435 }
00436
00437
00438 if (argc>3) {
00439 int i;
00440 for (i=2; i<argc; i+=2) {
00441 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00442 if (!strupncmp(argvcur, "molid", CMDLEN)) {
00443 if (Tcl_GetIntFromObj(interp, objv[i+1], &defmolid) != TCL_OK) {
00444 Tcl_AppendResult(interp, " measure ", geomname, ": bad molid", NULL);
00445 return TCL_ERROR;
00446 }
00447 } else if (!strupncmp(argvcur, "first", CMDLEN)) {
00448 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00449 Tcl_AppendResult(interp, " measure ", geomname, ": bad first frame value", NULL);
00450 return TCL_ERROR;
00451 }
00452 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00453 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00454 Tcl_AppendResult(interp, " measure ", geomname, ": bad last frame value", NULL);
00455 return TCL_ERROR;
00456 }
00457 } else if (!strupncmp(argvcur, "frame", CMDLEN)) {
00458 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "all")) {
00459 allframes = true;
00460 } else if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "last")) {
00461 frame=-2;
00462 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &frame) != TCL_OK) {
00463 Tcl_AppendResult(interp, " measure ", geomname, ": bad frame value", NULL);
00464 return TCL_ERROR;
00465 }
00466 } else {
00467 Tcl_AppendResult(interp, "measure ", geomname, ": invalid syntax, no such keyword: ", argvcur, NULL);
00468 return TCL_ERROR;
00469 }
00470 }
00471 }
00472
00473 if ((allframes || frame>=0) && (first>=0 || last>=0)) {
00474 Tcl_AppendResult(interp, "measure ", geomname, ": Ambiguous syntax: You cannot specify a frame AND a frame range (using first or last).", NULL);
00475 Tcl_AppendResult(interp, "\nUsage:\nmeasure ", geomname, " {<atomid1> [<molid1>]} {<atomid2> [<molid2>]} {<atomid3> [<molid3>]} {<atomid4> [<molid4>]}} [molid <default molid>] [frame <frame|all|last> | first <first> last <last>]", NULL);
00476 return TCL_ERROR;
00477 }
00478
00479 if (allframes) first=0;
00480
00481
00482 if (defmolid<0) defmolid = app->molecule_top();
00483
00484
00485 int i,numelem;
00486 Tcl_Obj **atmmol;
00487 for (i=0; i<numatms; i++) {
00488 if (Tcl_ListObjGetElements(interp, data[i], &numelem, &atmmol) != TCL_OK) {
00489 return TCL_ERROR;
00490 }
00491
00492 if (!numelem) {
00493 Tcl_AppendResult(interp, " measure ", geomname, ": empty atom index", NULL);
00494 return TCL_ERROR;
00495 }
00496
00497 if (Tcl_GetIntFromObj(interp, atmmol[0], atmid+i) != TCL_OK) {
00498 Tcl_AppendResult(interp, " measure ", geomname, ": bad atom index", NULL);
00499 return TCL_ERROR;
00500 }
00501
00502 if (numelem==2) {
00503 if (Tcl_GetIntFromObj(interp, atmmol[1], molid+i) != TCL_OK) {
00504 Tcl_AppendResult(interp, " measure ", geomname, ": bad molid", NULL);
00505 return TCL_ERROR;
00506 }
00507 } else molid[i] = defmolid;
00508 }
00509
00510
00511
00512 ResizeArray<float> gValues(1024);
00513 int ret_val;
00514 ret_val = measure_geom(app->moleculeList, molid, atmid, &gValues, frame, first, last,
00515 defmolid, MEASURE_DIHED);
00516 if (ret_val<0) {
00517 Tcl_AppendResult(interp, measure_error(ret_val), NULL);
00518 return TCL_ERROR;
00519 }
00520
00521 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00522 int numvalues = gValues.num();
00523 for (int count = 0; count < numvalues; count++) {
00524 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(gValues[count]));
00525 }
00526 Tcl_SetObjResult(interp, tcl_result);
00527
00528 return TCL_OK;
00529 }
00530
00531
00532
00533
00534 static int vmd_measure_angle(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00535 int first=-1, last=-1, frame=-1;
00536
00537 if(argc<2) {
00538 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "{{<atomid1> [<molid1>]} {<atomid2> [<molid2>]} {<atomid3> [<molid3>]}} [molid <default molid>] [frame <frame|all|last> | first <first> last <last>]");
00539 return TCL_ERROR;
00540 }
00541
00542 int molid[3];
00543 int atmid[3];
00544 int defmolid = -1;
00545 bool allframes = false;
00546
00547
00548 int numatms;
00549 Tcl_Obj **data;
00550 if (Tcl_ListObjGetElements(interp, objv[1], &numatms, &data) != TCL_OK) {
00551 Tcl_AppendResult(interp, " measure bond: bad syntax", NULL);
00552 Tcl_AppendResult(interp, " Usage: measure angle {{<atomid1> [<molid1>]} {<atomid2> [<molid2>]} {<atomid3> [<molid3>]}} [molid <default molid>] [frame <frame|all|last> | first <first> last <last>]", NULL);
00553 return TCL_ERROR;
00554 }
00555
00556 if (numatms!=3) {
00557 Tcl_AppendResult(interp, " measure angle: must specify exactly three atoms in a list", NULL);
00558 return TCL_ERROR;
00559 }
00560
00561
00562 if (argc>3) {
00563 int i;
00564 for (i=2; i<argc; i+=2) {
00565 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00566 if (!strupncmp(argvcur, "molid", CMDLEN)) {
00567 if (Tcl_GetIntFromObj(interp, objv[i+1], &defmolid) != TCL_OK) {
00568 Tcl_AppendResult(interp, " measure angle: bad molid", NULL);
00569 return TCL_ERROR;
00570 }
00571 } else if (!strupncmp(argvcur, "first", CMDLEN)) {
00572 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00573 Tcl_AppendResult(interp, " measure angle: bad first frame value", NULL);
00574 return TCL_ERROR;
00575 }
00576 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00577 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00578 Tcl_AppendResult(interp, " measure angle: bad last frame value", NULL);
00579 return TCL_ERROR;
00580 }
00581 } else if (!strupncmp(argvcur, "frame", CMDLEN)) {
00582 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "all")) {
00583 allframes = true;
00584 } else if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "last")) {
00585 frame=-2;
00586 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &frame) != TCL_OK) {
00587 Tcl_AppendResult(interp, " measure angle: bad frame value", NULL);
00588 return TCL_ERROR;
00589 }
00590 } else {
00591 Tcl_AppendResult(interp, " measure angle: invalid syntax, no such keyword: ", argvcur, NULL);
00592 return TCL_ERROR;
00593 }
00594 }
00595 }
00596
00597 if ((allframes || frame>=0) && (first>=0 || last>=0)) {
00598 Tcl_AppendResult(interp, "measure angle: Ambiguous syntax: You cannot specify a frame AND a frame range (using first or last).", NULL);
00599 Tcl_AppendResult(interp, "\nUsage:\nmeasure angle {<atomid1> [<molid1>]} {<atomid2> [<molid2>]} {<atomid3> [<molid3>]}} [molid <default molid>] [frame <frame|all|last> | first <first> last <last>]", NULL);
00600 return TCL_ERROR;
00601 }
00602
00603 if (allframes) first=0;
00604
00605
00606 if (defmolid<0) defmolid = app->molecule_top();
00607
00608
00609 int i,numelem;
00610 Tcl_Obj **atmmol;
00611 for (i=0; i<numatms; i++) {
00612 if (Tcl_ListObjGetElements(interp, data[i], &numelem, &atmmol) != TCL_OK) {
00613 return TCL_ERROR;
00614 }
00615
00616 if (!numelem) {
00617 Tcl_AppendResult(interp, " measure angle: empty atom index", NULL);
00618 return TCL_ERROR;
00619 }
00620
00621 if (Tcl_GetIntFromObj(interp, atmmol[0], atmid+i) != TCL_OK) {
00622 Tcl_AppendResult(interp, " measure angle: bad atom index", NULL);
00623 return TCL_ERROR;
00624 }
00625
00626 if (numelem==2) {
00627 if (Tcl_GetIntFromObj(interp, atmmol[1], molid+i) != TCL_OK) {
00628 Tcl_AppendResult(interp, " measure angle: bad molid", NULL);
00629 return TCL_ERROR;
00630 }
00631 } else molid[i] = defmolid;
00632 }
00633
00634
00635
00636 ResizeArray<float> gValues(1024);
00637 int ret_val;
00638 ret_val = measure_geom(app->moleculeList, molid, atmid, &gValues, frame, first, last,
00639 defmolid, MEASURE_ANGLE);
00640 if (ret_val<0) {
00641 printf("ERROR\n %s\n", measure_error(ret_val));
00642 Tcl_AppendResult(interp, measure_error(ret_val), NULL);
00643 return TCL_ERROR;
00644 }
00645
00646 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00647 int numvalues = gValues.num();
00648 for (int count = 0; count < numvalues; count++) {
00649 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(gValues[count]));
00650 }
00651 Tcl_SetObjResult(interp, tcl_result);
00652
00653 return TCL_OK;
00654 }
00655
00656
00657
00658 static int vmd_measure_bond(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00659 int first=-1, last=-1, frame=-1;
00660
00661 if (argc<2) {
00662 Tcl_WrongNumArgs(interp, 2, objv-1,
00663 (char *) "{{<atomid1> [<molid1>]} {<atomid2> [<molid2>]}} [molid <default molid>] [frame <frame|all|last> | first <first> last <last>]]");
00664 return TCL_ERROR;
00665 }
00666
00667 int molid[2];
00668 int atmid[2];
00669 int defmolid = -1;
00670 bool allframes = false;
00671
00672
00673 int numatms;
00674 Tcl_Obj **data;
00675 if (Tcl_ListObjGetElements(interp, objv[1], &numatms, &data) != TCL_OK) {
00676 Tcl_AppendResult(interp, " measure bond: bad syntax", NULL);
00677 Tcl_AppendResult(interp, " Usage: measure bond {{<atomid1> [<molid1>]} {<atomid2> [<molid2>]}} [molid <default>] [frame <frame|all|last> | first <first> last <last>]]", NULL);
00678 return TCL_ERROR;
00679 }
00680
00681 if (numatms!=2) {
00682 Tcl_AppendResult(interp, " measure bond: must specify exactly two atoms in a list", NULL);
00683 return TCL_ERROR;
00684 }
00685
00686
00687 if (argc>3) {
00688 int i;
00689 for (i=2; i<argc; i+=2) {
00690 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00691 if (!strupncmp(argvcur, "molid", CMDLEN)) {
00692 if (Tcl_GetIntFromObj(interp, objv[i+1], &defmolid) != TCL_OK) {
00693 Tcl_AppendResult(interp, " measure bond: bad molid", NULL);
00694 return TCL_ERROR;
00695 }
00696 } else if (!strupncmp(argvcur, "first", CMDLEN)) {
00697 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00698 Tcl_AppendResult(interp, " measure bond: bad first frame value", NULL);
00699 return TCL_ERROR;
00700 }
00701 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00702 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00703 Tcl_AppendResult(interp, " measure bond: bad last frame value", NULL);
00704 return TCL_ERROR;
00705 }
00706 } else if (!strupncmp(argvcur, "frame", CMDLEN)) {
00707 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "all")) {
00708 allframes = true;
00709 } else if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "last")) {
00710 frame=-2;
00711 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &frame) != TCL_OK) {
00712 Tcl_AppendResult(interp, " measure bond: bad frame value", NULL);
00713 return TCL_ERROR;
00714 }
00715 } else {
00716 Tcl_AppendResult(interp, " measure bond: invalid syntax, no such keyword: ", argvcur, NULL);
00717 return TCL_ERROR;
00718 }
00719 }
00720 }
00721
00722 if ((allframes || frame>=0) && (first>=0 || last>=0)) {
00723 Tcl_AppendResult(interp, "measure bond: Ambiguous syntax: You cannot specify a frame AND a frame range (using first or last).", NULL);
00724 Tcl_AppendResult(interp, "\nUsage:\nmeasure bond {{<atomid1> [<molid1>]} {<atomid2> [<molid2>]}} [molid <default>] [frame <frame|all|last> | first <first> last <last>]", NULL);
00725 return TCL_ERROR;
00726 }
00727
00728 if (allframes) first=0;
00729
00730
00731 if (defmolid<0) defmolid = app->molecule_top();
00732
00733
00734 int i,numelem;
00735 Tcl_Obj **atmmol;
00736 for (i=0; i<numatms; i++) {
00737 if (Tcl_ListObjGetElements(interp, data[i], &numelem, &atmmol) != TCL_OK) {
00738 return TCL_ERROR;
00739 }
00740
00741 if (!numelem) {
00742 Tcl_AppendResult(interp, " measure bond: empty atom index", NULL);
00743 return TCL_ERROR;
00744 }
00745
00746 if (Tcl_GetIntFromObj(interp, atmmol[0], atmid+i) != TCL_OK) {
00747 Tcl_AppendResult(interp, " measure bond: bad atom index", NULL);
00748 return TCL_ERROR;
00749 }
00750
00751 if (numelem==2) {
00752 if (Tcl_GetIntFromObj(interp, atmmol[1], molid+i) != TCL_OK) {
00753 Tcl_AppendResult(interp, " measure bond: bad molid", NULL);
00754 return TCL_ERROR;
00755 }
00756 } else molid[i] = defmolid;
00757 }
00758
00759
00760
00761 ResizeArray<float> gValues(1024);
00762 int ret_val;
00763 ret_val = measure_geom(app->moleculeList, molid, atmid, &gValues, frame, first, last,
00764 defmolid, MEASURE_BOND);
00765 if (ret_val<0) {
00766 printf("ERROR\n %s\n", measure_error(ret_val));
00767 Tcl_AppendResult(interp, measure_error(ret_val), NULL);
00768 return TCL_ERROR;
00769 }
00770
00771 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00772 int numvalues = gValues.num();
00773 for (int count = 0; count < numvalues; count++) {
00774 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(gValues[count]));
00775 }
00776 Tcl_SetObjResult(interp, tcl_result);
00777
00778 return TCL_OK;
00779 }
00780
00781
00782
00783
00784 static int vmd_measure_rmsf(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00785 int first = 0;
00786 int last = -1;
00787 int step = 1;
00788
00789 if (argc < 2 || argc > 8) {
00790 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<sel> [first <first>] [last <last>] [step <step>]");
00791 return TCL_ERROR;
00792 }
00793 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL)
00794 );
00795 if (!sel) {
00796 Tcl_AppendResult(interp, "measure rmsf: no atom selection", NULL);
00797 return TCL_ERROR;
00798 }
00799
00800 int i;
00801 for (i=2; i<argc; i+=2) {
00802 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00803 if (!strupncmp(argvcur, "first", CMDLEN)) {
00804 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00805 Tcl_AppendResult(interp, "measure rmsf: bad first frame value", NULL);
00806 return TCL_ERROR;
00807 }
00808 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00809 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00810 Tcl_AppendResult(interp, "measure rmsf: bad last frame value", NULL);
00811 return TCL_ERROR;
00812 }
00813 } else if (!strupncmp(argvcur, "step", CMDLEN)) {
00814 if (Tcl_GetIntFromObj(interp, objv[i+1], &step) != TCL_OK) {
00815 Tcl_AppendResult(interp, "measure rmsf: bad frame step value", NULL);
00816 return TCL_ERROR;
00817 }
00818 } else {
00819 Tcl_AppendResult(interp, "measure rmsf: invalid syntax, no such keyword: ", argvcur, NULL);
00820 return TCL_ERROR;
00821 }
00822 }
00823
00824 float *rmsf = new float[sel->selected];
00825 int ret_val = measure_rmsf(sel, app->moleculeList, first, last, step, rmsf);
00826 if (ret_val < 0) {
00827 Tcl_AppendResult(interp, "measure rmsf: ", measure_error(ret_val), NULL);
00828 delete [] rmsf;
00829 return TCL_ERROR;
00830 }
00831
00832 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00833
00834 for (i=0; i<sel->selected; i++) {
00835 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(rmsf[i]));
00836 }
00837
00838 Tcl_SetObjResult(interp, tcl_result);
00839
00840 delete [] rmsf;
00841
00842 return TCL_OK;
00843 }
00844
00845
00846
00847 static int vmd_measure_rgyr(VMDApp *app, int argc, Tcl_Obj *const objv[], Tcl_Interp *interp)
00848 {
00849 if (argc != 2 && argc != 4 ) {
00850 Tcl_WrongNumArgs(interp, 2, objv-1,
00851 (char *)"<selection> [weight <weights>]");
00852 return TCL_ERROR;
00853 }
00854 if (argc == 4 && strcmp(Tcl_GetStringFromObj(objv[2],NULL), "weight")) {
00855 Tcl_SetResult(interp, (char *) "measure rgyr: parameter can only be 'weight'", TCL_STATIC);
00856 return TCL_ERROR;
00857 }
00858
00859
00860 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
00861 if (!sel) {
00862 Tcl_SetResult(interp, (char *) "measure rgyr: no atom selection", TCL_STATIC);
00863 return TCL_ERROR;
00864 }
00865
00866
00867 float *weight = new float[sel->selected];
00868 {
00869 int ret_val;
00870 if (argc == 2) {
00871 ret_val = tcl_get_weights(interp, app, sel, NULL, weight);
00872 } else {
00873 ret_val = tcl_get_weights(interp, app, sel, objv[3], weight);
00874 }
00875 if (ret_val < 0) {
00876 Tcl_AppendResult(interp, "measure rgyr: ", measure_error(ret_val),
00877 NULL);
00878 delete [] weight;
00879 return TCL_ERROR;
00880 }
00881 }
00882 float rgyr;
00883 int ret_val = measure_rgyr(sel, app->moleculeList, weight, &rgyr);
00884 delete [] weight;
00885 if (ret_val < 0) {
00886 Tcl_AppendResult(interp, "measure rgyr: ", measure_error(ret_val),
00887 NULL);
00888 return TCL_ERROR;
00889 }
00890 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rgyr));
00891 return TCL_OK;
00892 }
00893
00894
00895
00896
00897
00898
00899 static int vmd_measure_minmax(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00900 const float *radii = NULL;
00901 if (argc != 2 && argc != 3) {
00902 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<selection> [-withradii]");
00903 return TCL_ERROR;
00904 }
00905 if (argc == 3 && strcmp(Tcl_GetStringFromObj(objv[2],NULL), "-withradii")) {
00906 Tcl_SetResult(interp, (char *) "measure minmax: parameter can only be '-withradii'", TCL_STATIC);
00907 return TCL_ERROR;
00908 }
00909
00910 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
00911 if (!sel) {
00912 Tcl_AppendResult(interp, "measure minmax: no atom selection", NULL);
00913 return TCL_ERROR;
00914 }
00915
00916 float min_coord[3], max_coord[3];
00917 const float *framepos = sel->coordinates(app->moleculeList);
00918 if (!framepos) return TCL_ERROR;
00919
00920
00921 if (argc == 3) {
00922 Molecule *mol = app->moleculeList->mol_from_id(sel->molid());
00923 radii = mol->extraflt.data("radius");
00924 }
00925
00926 int ret_val = measure_minmax(sel->num_atoms, sel->on, framepos, radii,
00927 min_coord, max_coord);
00928 if (ret_val < 0) {
00929 Tcl_AppendResult(interp, "measure minmax: ", measure_error(ret_val));
00930 return TCL_ERROR;
00931 }
00932
00933 Tcl_Obj *list1 = Tcl_NewListObj(0, NULL);
00934 Tcl_Obj *list2 = Tcl_NewListObj(0, NULL);
00935 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00936
00937 Tcl_ListObjAppendElement(interp, list1, Tcl_NewDoubleObj(min_coord[0]));
00938 Tcl_ListObjAppendElement(interp, list1, Tcl_NewDoubleObj(min_coord[1]));
00939 Tcl_ListObjAppendElement(interp, list1, Tcl_NewDoubleObj(min_coord[2]));
00940
00941 Tcl_ListObjAppendElement(interp, list2, Tcl_NewDoubleObj(max_coord[0]));
00942 Tcl_ListObjAppendElement(interp, list2, Tcl_NewDoubleObj(max_coord[1]));
00943 Tcl_ListObjAppendElement(interp, list2, Tcl_NewDoubleObj(max_coord[2]));
00944
00945 Tcl_ListObjAppendElement(interp, tcl_result, list1);
00946 Tcl_ListObjAppendElement(interp, tcl_result, list2);
00947 Tcl_SetObjResult(interp, tcl_result);
00948
00949 return TCL_OK;
00950 }
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 static int vmd_measure_rmsd(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp)
00971 {
00972 if (argc !=3 && argc != 5) {
00973 Tcl_WrongNumArgs(interp, 2, objv-1,
00974 (char *)"<sel1> <sel2> [weight <weights>]");
00975 return TCL_ERROR;
00976 }
00977
00978 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
00979 AtomSel *sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2],NULL));
00980 if (!sel1 || !sel2) {
00981 Tcl_AppendResult(interp, "measure rmsd: no atom selection", NULL);
00982 return TCL_ERROR;
00983 }
00984
00985 if (sel1->selected != sel2->selected) {
00986 Tcl_AppendResult(interp, "measure rmsd: selections must have the same number of atoms", NULL);
00987 return TCL_ERROR;
00988 }
00989 if (!sel1->selected) {
00990 Tcl_AppendResult(interp, "measure rmsd: no atoms selected", NULL);
00991 return TCL_ERROR;
00992 }
00993 float *weight = new float[sel1->selected];
00994 {
00995 int ret_val;
00996 if (argc == 3) {
00997 ret_val = tcl_get_weights(interp, app, sel1, NULL, weight);
00998 } else {
00999 ret_val = tcl_get_weights(interp, app, sel1, objv[4], weight);
01000 }
01001 if (ret_val < 0) {
01002 Tcl_AppendResult(interp, "measure rmsd: ", measure_error(ret_val),
01003 NULL);
01004 delete [] weight;
01005 return TCL_ERROR;
01006 }
01007 }
01008
01009 {
01010 float rmsd = 0;
01011 const float *x = sel1->coordinates(app->moleculeList);
01012 const float *y = sel2->coordinates(app->moleculeList);
01013 if (!x || !y) {
01014 delete [] weight;
01015 return TCL_ERROR;
01016 }
01017 int ret_val = measure_rmsd(sel1, sel2, sel1->selected, x, y, weight, &rmsd);
01018 delete [] weight;
01019 if (ret_val < 0) {
01020 Tcl_AppendResult(interp, "measure rmsd: ", measure_error(ret_val),
01021 NULL);
01022 return TCL_ERROR;
01023 }
01024 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rmsd));
01025 }
01026 return TCL_OK;
01027 }
01028
01030
01031 static int vmd_measure_fit(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp)
01032 {
01033 AtomSel *sel1, *sel2;
01034 int *order = NULL;
01035 float *weight = NULL;
01036 int rc;
01037
01038 if (argc != 3 && argc != 5
01039 && argc != 7) {
01040 Tcl_WrongNumArgs(interp, 2, objv-1,
01041 (char *)"<sel1> <sel2> [weight <weights>] [order <index list>]");
01042 return TCL_ERROR;
01043 } else if (argc == 5
01044 && strcmp("weight", Tcl_GetStringFromObj(objv[3], NULL))
01045 && strcmp("order", Tcl_GetStringFromObj(objv[3], NULL))) {
01046 Tcl_WrongNumArgs(interp, 2, objv-1,
01047 (char *)"<sel1> <sel2> [weight <weights>] [order <index list>]");
01048 return TCL_ERROR;
01049 } else if (argc == 7 &&
01050 (strcmp("weight", Tcl_GetStringFromObj(objv[3], NULL)) ||
01051 strcmp("order", Tcl_GetStringFromObj(objv[5], NULL)))) {
01052 Tcl_WrongNumArgs(interp, 2, objv-1,
01053 (char *)"<sel1> <sel2> [weight <weights>] [order <index list>]");
01054 return TCL_ERROR;
01055 }
01056
01057
01058 sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
01059 sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2],NULL));
01060
01061 if (!sel1 || !sel2) {
01062 Tcl_AppendResult(interp, "measure fit: no atom selection", NULL);
01063 return TCL_ERROR;
01064 }
01065
01066 int num = sel1->selected;
01067 if (!num) {
01068 Tcl_AppendResult(interp, "measure fit: no atoms selected", NULL);
01069 return TCL_ERROR;
01070 }
01071 if (num != sel2->selected) {
01072 Tcl_AppendResult(interp, "measure fit: selections must have the same number of atoms", NULL);
01073 return TCL_ERROR;
01074 }
01075
01076
01077 weight = new float[num];
01078 if (argc > 3 && !strcmp("weight", Tcl_GetStringFromObj(objv[3], NULL))) {
01079
01080 rc = tcl_get_weights(interp, app, sel1, objv[4], weight);
01081 } else {
01082
01083 rc = tcl_get_weights(interp, app, sel1, NULL, weight);
01084 }
01085 if (rc < 0) {
01086 Tcl_AppendResult(interp, "measure fit: ", measure_error(rc), NULL);
01087 delete [] weight;
01088 return TCL_ERROR;
01089 }
01090
01091
01092 int orderparam = 0;
01093 if (argc == 5 && !strcmp("order", Tcl_GetStringFromObj(objv[3], NULL))) {
01094 orderparam = 4;
01095 } else if (argc == 7 && !strcmp("order", Tcl_GetStringFromObj(objv[5], NULL))) {
01096 orderparam = 6;
01097 }
01098
01099 if (orderparam != 0) {
01100
01101 order = new int[num];
01102 rc = tcl_get_orders(interp, num, objv[orderparam], order);
01103 if (rc < 0) {
01104 Tcl_AppendResult(interp, "measure fit: ", measure_error(rc), NULL);
01105 delete [] order;
01106 return TCL_ERROR;
01107 }
01108 }
01109
01110
01111 Matrix4 T;
01112 const float *x = sel1->coordinates(app->moleculeList);
01113 const float *y = sel2->coordinates(app->moleculeList);
01114
01115 int ret_val = MEASURE_ERR_NOMOLECULE;
01116 if (x && y)
01117 ret_val = measure_fit(sel1, sel2, x, y, weight, order, &T);
01118
01119 delete [] weight;
01120
01121 if (order != NULL)
01122 delete [] order;
01123
01124 if (ret_val < 0) {
01125 Tcl_AppendResult(interp, "measure fit: ", measure_error(ret_val), NULL);
01126 return TCL_ERROR;
01127 }
01128
01129
01130 tcl_append_matrix(interp, T.mat);
01131 return TCL_OK;
01132 }
01133
01135
01136 static int vmd_measure_inverse(int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01137
01138 if (argc != 2) {
01139 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<matrix>");
01140 return TCL_ERROR;
01141 }
01142
01143 Matrix4 inv;
01144 if (tcl_get_matrix("measure inverse: ",interp,objv[1],inv.mat) != TCL_OK) {
01145 return TCL_ERROR;
01146 }
01147 if (inv.inverse()) {
01148 Tcl_AppendResult(interp, "Singular Matrix; inverse not computed", NULL);
01149 return TCL_ERROR;
01150 }
01151 tcl_append_matrix(interp, inv.mat);
01152 return TCL_OK;
01153 }
01154
01155
01156 static int vmd_measure_contacts(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01157
01158
01159 if (argc != 3 && argc != 4) {
01160 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<cutoff> <sel1> [<sel2>]");
01161 return TCL_ERROR;
01162 }
01163 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2],NULL));
01164 if (!sel1) {
01165 Tcl_AppendResult(interp, "measure contacts: no atom selection", NULL);
01166 return TCL_ERROR;
01167 }
01168 AtomSel *sel2 = NULL;
01169 if (argc == 4) {
01170 sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[3],NULL));
01171 if (!sel2) {
01172 Tcl_AppendResult(interp, "measure contacts: no atom selection", NULL);
01173 return TCL_ERROR;
01174 }
01175 }
01176 if (!sel2) sel2 = sel1;
01177
01178 double cutoff;
01179 if (Tcl_GetDoubleFromObj(interp, objv[1], &cutoff) != TCL_OK)
01180 return TCL_ERROR;
01181
01182 const float *pos1 = sel1->coordinates(app->moleculeList);
01183 const float *pos2 = sel2->coordinates(app->moleculeList);
01184 if (!pos1 || !pos2) {
01185 Tcl_AppendResult(interp, "measure contacts: error, molecule contains no coordinates", NULL);
01186 return TCL_ERROR;
01187 }
01188 Molecule *mol1 = app->moleculeList->mol_from_id(sel1->molid());
01189 Molecule *mol2 = app->moleculeList->mol_from_id(sel2->molid());
01190
01191 GridSearchPair *pairlist = vmd_gridsearch3(pos1, sel1->num_atoms, sel1->on, pos2, sel2->num_atoms, sel2->on, (float) cutoff, -1, (sel1->num_atoms + sel2->num_atoms) * 27);
01192 GridSearchPair *p, *tmp;
01193 Tcl_Obj *list1 = Tcl_NewListObj(0, NULL);
01194 Tcl_Obj *list2 = Tcl_NewListObj(0, NULL);
01195 for (p=pairlist; p != NULL; p=tmp) {
01196
01197 MolAtom *a1 = mol1->atom(p->ind1);
01198 if (mol1 != mol2 || !a1->bonded(p->ind2)) {
01199 Tcl_ListObjAppendElement(interp, list1, Tcl_NewIntObj(p->ind1));
01200 Tcl_ListObjAppendElement(interp, list2, Tcl_NewIntObj(p->ind2));
01201 }
01202 tmp = p->next;
01203 free(p);
01204 }
01205 Tcl_Obj *result = Tcl_NewListObj(0, NULL);
01206 Tcl_ListObjAppendElement(interp, result, list1);
01207 Tcl_ListObjAppendElement(interp, result, list2);
01208 Tcl_SetObjResult(interp, result);
01209 return TCL_OK;
01210 }
01211
01212
01213
01214
01215 static int vmd_measure_gofr(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01216 int i;
01217
01218 double rmax=10.0;
01219 double delta=0.1;
01220 int usepbc=0;
01221 int selupdate=0;
01222 int first=-1, last=-1, step=1;
01223 int rc;
01224
01225
01226 const char *argerrmsg = "<sel1> <sel2> [delta <value>] [rmax <value>] [usepbc <bool>] [selupdate <bool>] [first <first>] [last <last>] [step <step>]";
01227
01228
01229 if ((argc < 3) || (argc > 17) || (argc % 2 == 0) ) {
01230 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
01231 return TCL_ERROR;
01232 }
01233
01234
01235 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1], NULL));
01236 if (!sel1) {
01237 Tcl_AppendResult(interp, "measure gofr: invalid first atom selection", NULL);
01238 return TCL_ERROR;
01239 }
01240
01241 AtomSel *sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2], NULL));
01242 if (!sel2) {
01243 Tcl_AppendResult(interp, "measure gofr: invalid second atom selection", NULL);
01244 return TCL_ERROR;
01245 }
01246
01247
01248 for (i=3; i<argc; i+=2) {
01249 const char *opt = Tcl_GetStringFromObj(objv[i], NULL);
01250 if (i==(argc-1)) {
01251 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
01252 return TCL_ERROR;
01253 }
01254 if (!strcmp(opt, "delta")) {
01255 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &delta) != TCL_OK)
01256 return TCL_ERROR;
01257 if (delta <= 0.0) {
01258 Tcl_AppendResult(interp, "measure gofr: invalid 'delta' value", NULL);
01259 return TCL_ERROR;
01260 }
01261 } else if (!strcmp(opt, "rmax")) {
01262 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &rmax) != TCL_OK)
01263 return TCL_ERROR;
01264 if (rmax <= 0.0) {
01265 Tcl_AppendResult(interp, "measure gofr: invalid 'rmax' value", NULL);
01266 return TCL_ERROR;
01267 }
01268 } else if (!strcmp(opt, "usepbc")) {
01269 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &usepbc) != TCL_OK)
01270 return TCL_ERROR;
01271 } else if (!strcmp(opt, "selupdate")) {
01272 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &selupdate) != TCL_OK)
01273 return TCL_ERROR;
01274 } else if (!strcmp(opt, "first")) {
01275 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK)
01276 return TCL_ERROR;
01277 } else if (!strcmp(opt, "last")) {
01278 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK)
01279 return TCL_ERROR;
01280 } else if (!strcmp(opt, "step")) {
01281 if (Tcl_GetIntFromObj(interp, objv[i+1], &step) != TCL_OK)
01282 return TCL_ERROR;
01283 } else {
01284 Tcl_AppendResult(interp, "unknown keyword '", opt, "'. usage: measure gofr ", argerrmsg,NULL);
01285 return TCL_ERROR;
01286 }
01287 }
01288
01289
01290 int count_h = (int)(rmax / delta + 1.0);
01291 double *gofr = new double[count_h];
01292 double *numint = new double[count_h];
01293 double *histog = new double[count_h];
01294 int *framecntr = new int[3];
01295
01296
01297 rc = measure_gofr(sel1, sel2, app->moleculeList,
01298 count_h, gofr, numint, histog,
01299 (float) delta,
01300 first, last, step, framecntr,
01301 usepbc, selupdate);
01302
01303
01304 if (rc != MEASURE_NOERR) {
01305 Tcl_AppendResult(interp, "measure gofr: error during g(r) calculation.", NULL);
01306 return TCL_ERROR;
01307 }
01308
01309
01310
01311 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
01312 Tcl_Obj *tcl_rlist = Tcl_NewListObj(0, NULL);
01313 Tcl_Obj *tcl_gofr = Tcl_NewListObj(0, NULL);
01314 Tcl_Obj *tcl_numint = Tcl_NewListObj(0, NULL);
01315 Tcl_Obj *tcl_histog = Tcl_NewListObj(0, NULL);
01316 Tcl_Obj *tcl_frames = Tcl_NewListObj(0, NULL);
01317
01318
01319 for (i=0; i<count_h; i++) {
01320 Tcl_ListObjAppendElement(interp, tcl_rlist, Tcl_NewDoubleObj(delta * ((double)i + 0.5)));
01321 Tcl_ListObjAppendElement(interp, tcl_gofr, Tcl_NewDoubleObj(gofr[i]));
01322 Tcl_ListObjAppendElement(interp, tcl_numint, Tcl_NewDoubleObj(numint[i]));
01323 Tcl_ListObjAppendElement(interp, tcl_histog, Tcl_NewDoubleObj(histog[i]));
01324 }
01325
01326
01327
01328 Tcl_ListObjAppendElement(interp, tcl_frames, Tcl_NewIntObj(framecntr[0]));
01329 Tcl_ListObjAppendElement(interp, tcl_frames, Tcl_NewIntObj(framecntr[1]));
01330 Tcl_ListObjAppendElement(interp, tcl_frames, Tcl_NewIntObj(framecntr[2]));
01331
01332
01333 Tcl_ListObjAppendElement(interp, tcl_result, tcl_rlist);
01334 Tcl_ListObjAppendElement(interp, tcl_result, tcl_gofr);
01335 Tcl_ListObjAppendElement(interp, tcl_result, tcl_numint);
01336 Tcl_ListObjAppendElement(interp, tcl_result, tcl_histog);
01337 Tcl_ListObjAppendElement(interp, tcl_result, tcl_frames);
01338 Tcl_SetObjResult(interp, tcl_result);
01339
01340 delete [] gofr;
01341 delete [] numint;
01342 delete [] histog;
01343 delete [] framecntr;
01344 return TCL_OK;
01345 }
01346
01347
01348
01349
01350 static int vmd_measure_rdf(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01351 int i;
01352
01353 double rmax=10.0;
01354 double delta=0.1;
01355 int usepbc=0;
01356 int selupdate=0;
01357 int first=-1, last=-1, step=1;
01358 int rc;
01359
01360
01361 const char *argerrmsg = "<sel1> <sel2> [delta <value>] [rmax <value>] [usepbc <bool>] [selupdate <bool>] [first <first>] [last <last>] [step <step>]";
01362
01363
01364 if ((argc < 3) || (argc > 17) || (argc % 2 == 0) ) {
01365 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
01366 return TCL_ERROR;
01367 }
01368
01369
01370 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1], NULL));
01371 if (!sel1) {
01372 Tcl_AppendResult(interp, "measure rdf: invalid first atom selection", NULL);
01373 return TCL_ERROR;
01374 }
01375
01376 AtomSel *sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2], NULL));
01377 if (!sel2) {
01378 Tcl_AppendResult(interp, "measure rdf: invalid second atom selection", NULL);
01379 return TCL_ERROR;
01380 }
01381
01382
01383 for (i=3; i<argc; i+=2) {
01384 const char *opt = Tcl_GetStringFromObj(objv[i], NULL);
01385 if (i==(argc-1)) {
01386 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
01387 return TCL_ERROR;
01388 }
01389 if (!strcmp(opt, "delta")) {
01390 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &delta) != TCL_OK)
01391 return TCL_ERROR;
01392 if (delta <= 0.0) {
01393 Tcl_AppendResult(interp, "measure rdf: invalid 'delta' value", NULL);
01394 return TCL_ERROR;
01395 }
01396 } else if (!strcmp(opt, "rmax")) {
01397 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &rmax) != TCL_OK)
01398 return TCL_ERROR;
01399 if (rmax <= 0.0) {
01400 Tcl_AppendResult(interp, "measure rdf: invalid 'rmax' value", NULL);
01401 return TCL_ERROR;
01402 }
01403 } else if (!strcmp(opt, "usepbc")) {
01404 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &usepbc) != TCL_OK)
01405 return TCL_ERROR;
01406 } else if (!strcmp(opt, "selupdate")) {
01407 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &selupdate) != TCL_OK)
01408 return TCL_ERROR;
01409 } else if (!strcmp(opt, "first")) {
01410 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK)
01411 return TCL_ERROR;
01412 } else if (!strcmp(opt, "last")) {
01413 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK)
01414 return TCL_ERROR;
01415 } else if (!strcmp(opt, "step")) {
01416 if (Tcl_GetIntFromObj(interp, objv[i+1], &step) != TCL_OK)
01417 return TCL_ERROR;
01418 } else {
01419 Tcl_AppendResult(interp, "unknown keyword '", opt, "'. usage: measure rdf ", argerrmsg,NULL);
01420 return TCL_ERROR;
01421 }
01422 }
01423
01424
01425 int count_h = (int)(rmax / delta + 1.0);
01426 double *gofr = new double[count_h];
01427 double *numint = new double[count_h];
01428 double *histog = new double[count_h];
01429 int *framecntr = new int[3];
01430
01431
01432 rc = measure_rdf(app, sel1, sel2, app->moleculeList,
01433 count_h, gofr, numint, histog,
01434 (float) delta,
01435 first, last, step, framecntr,
01436 usepbc, selupdate);
01437
01438
01439 if (rc != MEASURE_NOERR) {
01440 Tcl_AppendResult(interp, "measure rdf: error during rdf calculation.", NULL);
01441 return TCL_ERROR;
01442 }
01443
01444
01445
01446 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
01447 Tcl_Obj *tcl_rlist = Tcl_NewListObj(0, NULL);
01448 Tcl_Obj *tcl_gofr = Tcl_NewListObj(0, NULL);
01449 Tcl_Obj *tcl_numint = Tcl_NewListObj(0, NULL);
01450 Tcl_Obj *tcl_histog = Tcl_NewListObj(0, NULL);
01451 Tcl_Obj *tcl_frames = Tcl_NewListObj(0, NULL);
01452
01453
01454 for (i=0; i<count_h; i++) {
01455 Tcl_ListObjAppendElement(interp, tcl_rlist, Tcl_NewDoubleObj(delta * ((double)i + 0.5)));
01456 Tcl_ListObjAppendElement(interp, tcl_gofr, Tcl_NewDoubleObj(gofr[i]));
01457 Tcl_ListObjAppendElement(interp, tcl_numint, Tcl_NewDoubleObj(numint[i]));
01458 Tcl_ListObjAppendElement(interp, tcl_histog, Tcl_NewDoubleObj(histog[i]));
01459 }
01460
01461
01462
01463 Tcl_ListObjAppendElement(interp, tcl_frames, Tcl_NewIntObj(framecntr[0]));
01464 Tcl_ListObjAppendElement(interp, tcl_frames, Tcl_NewIntObj(framecntr[1]));
01465 Tcl_ListObjAppendElement(interp, tcl_frames, Tcl_NewIntObj(framecntr[2]));
01466
01467
01468 Tcl_ListObjAppendElement(interp, tcl_result, tcl_rlist);
01469 Tcl_ListObjAppendElement(interp, tcl_result, tcl_gofr);
01470 Tcl_ListObjAppendElement(interp, tcl_result, tcl_numint);
01471 Tcl_ListObjAppendElement(interp, tcl_result, tcl_histog);
01472 Tcl_ListObjAppendElement(interp, tcl_result, tcl_frames);
01473 Tcl_SetObjResult(interp, tcl_result);
01474
01475 delete [] gofr;
01476 delete [] numint;
01477 delete [] histog;
01478 delete [] framecntr;
01479 return TCL_OK;
01480 }
01481
01482
01484 static int vmd_measure_cluster(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01485 int i,j;
01486
01487 int algorithm=0;
01488 int likeness=MEASURE_DIST_FITRMSD;
01489 int numcluster=5;
01490 double cutoff=1.0;
01491 float *weights=NULL;
01492 int selupdate=0;
01493 int first=0, last=-1, step=1;
01494 int rc;
01495
01496
01497 const char *argerrmsg = "<sel> [num <#clusters>] [distfunc <flag>] "
01498 "[cutoff <cutoff>] [first <first>] [last <last>] [step <step>] "
01499 "[selupdate <bool>] [weight <weights>]";
01500
01501
01502 if ((argc < 2) || (argc > 19) || ((argc-1) % 2 == 0) ) {
01503 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
01504 return TCL_ERROR;
01505 }
01506
01507
01508 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1], NULL));
01509 if (!sel) {
01510 Tcl_AppendResult(interp, "measure cluster: invalid atom selection", NULL);
01511 return TCL_ERROR;
01512 }
01513 if (!app->molecule_valid_id(sel->molid())) return MEASURE_ERR_NOMOLECULE;
01514
01515
01516 for (i=2; i<argc; i+=2) {
01517 const char *opt = Tcl_GetStringFromObj(objv[i], NULL);
01518 if (i==(argc-1)) {
01519 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
01520 return TCL_ERROR;
01521 }
01522 if (!strcmp(opt, "num")) {
01523 if (Tcl_GetIntFromObj(interp, objv[i+1], &numcluster) != TCL_OK)
01524 return TCL_ERROR;
01525 if (numcluster < 1) {
01526 Tcl_AppendResult(interp, "measure cluster: invalid 'num' value (cannot be smaller than 1)", NULL);
01527 return TCL_ERROR;
01528 }
01529 } else if (!strcmp(opt, "cutoff")) {
01530 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &cutoff) != TCL_OK)
01531 return TCL_ERROR;
01532 if (cutoff <= 0.0) {
01533 Tcl_AppendResult(interp, "measure cluster: invalid 'cutoff' value (should be larger than 0.0)", NULL);
01534 return TCL_ERROR;
01535 }
01536 } else if (!strcmp(opt, "distfunc")) {
01537 char *argstr = Tcl_GetStringFromObj(objv[i+1], NULL);
01538 if (!strcmp(argstr,"rmsd")) {
01539 likeness = MEASURE_DIST_RMSD;
01540 } else if (!strcmp(argstr,"fitrmsd")) {
01541 likeness = MEASURE_DIST_FITRMSD;
01542 } else if (!strcmp(argstr,"rgyrd")) {
01543 likeness = MEASURE_DIST_RGYRD;
01544 } else {
01545 Tcl_AppendResult(interp, "measure cluster: unknown distance function (supported are 'rmsd', 'rgyrd' and 'fitrmsd')", NULL);
01546 return TCL_ERROR;
01547 }
01548 } else if (!strcmp(opt, "selupdate")) {
01549 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &selupdate) != TCL_OK)
01550 return TCL_ERROR;
01551 } else if (!strcmp(opt, "weight")) {
01552
01553
01554
01555
01556 const char *weight_string = Tcl_GetStringFromObj(objv[i+1], NULL);
01557 weights = new float[sel->num_atoms];
01558
01559 if (!weight_string || !strcmp(weight_string, "none")) {
01560 for (j=0; j<sel->num_atoms; j++) weights[j]=1.0f;
01561 } else {
01562
01563 SymbolTable *atomSelParser = app->atomSelParser;
01564
01565
01566 atomsel_ctxt context(atomSelParser,
01567 app->moleculeList->mol_from_id(sel->molid()),
01568 sel->which_frame, NULL);
01569
01570 int fctn = atomSelParser->find_attribute(weight_string);
01571 if (fctn >= 0) {
01572
01573
01574
01575 if (atomSelParser->fctns.data(fctn)->returns_a != SymbolTableElement::IS_FLOAT) {
01576 Tcl_AppendResult(interp, "weight attribute must have floating point values", NULL);
01577 delete [] weights;
01578 return MEASURE_ERR_BADWEIGHTPARM;
01579 }
01580
01581 double *tmp_data = new double[sel->num_atoms];
01582 int *all_on = new int[sel->num_atoms];
01583 for (j=0; j<sel->num_atoms; j++) all_on[j]=1;
01584
01585 atomSelParser->fctns.data(fctn)->keyword_double(
01586 &context, sel->num_atoms, tmp_data, all_on);
01587
01588 for (j=0; j<sel->num_atoms; j++) weights[j] = (float)tmp_data[j];
01589
01590
01591 delete [] tmp_data;
01592 delete [] all_on;
01593 }
01594 }
01595 } else if (!strcmp(opt, "first")) {
01596 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK)
01597 return TCL_ERROR;
01598 } else if (!strcmp(opt, "last")) {
01599 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK)
01600 return TCL_ERROR;
01601 } else if (!strcmp(opt, "step")) {
01602 if (Tcl_GetIntFromObj(interp, objv[i+1], &step) != TCL_OK)
01603 return TCL_ERROR;
01604 } else {
01605 Tcl_AppendResult(interp, "unknown keyword '", opt, "'. usage: measure cluster ", argerrmsg,NULL);
01606 return TCL_ERROR;
01607 }
01608 }
01609
01610
01611 if (!weights) {
01612 weights = new float[sel->num_atoms];
01613 for (j=0; j<sel->num_atoms; j++) weights[j]=1.0f;
01614 }
01615
01616
01617
01618
01619
01620 int *clustersize = new int [numcluster+1];
01621 int **clusterlist = new int *[numcluster+1];
01622
01623
01624 rc = measure_cluster(sel, app->moleculeList, numcluster, algorithm, likeness, cutoff,
01625 clustersize, clusterlist, first, last, step, selupdate, weights);
01626
01627 if (weights) delete [] weights;
01628
01629
01630 if (rc != MEASURE_NOERR) {
01631 Tcl_AppendResult(interp, "measure cluster: error during cluster analysis calculation.", NULL);
01632 return TCL_ERROR;
01633 }
01634
01635
01636
01637 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
01638
01639 for (i=0; i <= numcluster; ++i) {
01640 int j;
01641 Tcl_Obj *tcl_clist = Tcl_NewListObj(0, NULL);
01642 for (j=0; j < clustersize[i]; ++j) {
01643 Tcl_ListObjAppendElement(interp, tcl_clist, Tcl_NewIntObj(clusterlist[i][j]));
01644 }
01645 Tcl_ListObjAppendElement(interp, tcl_result, tcl_clist);
01646 }
01647 Tcl_SetObjResult(interp, tcl_result);
01648
01649
01650 for (i=0; i <= numcluster; ++i)
01651 delete[] clusterlist[i];
01652
01653 delete[] clusterlist;
01654 delete[] clustersize;
01655
01656 return TCL_OK;
01657 }
01658
01660 static int vmd_measure_clustsize(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01661 int i;
01662
01663 double cutoff=3.0;
01664 char *storesize=NULL;
01665 char *storenum=NULL;
01666 int usepbc=0;
01667 int minsize=2;
01668 int numshared=1;
01669 int rc;
01670
01671
01672 const char *argerrmsg = "<sel> [cutoff <float>] [minsize <num>] [numshared <num>] "
01673 "[usepbc <bool>] [storesize <fieldname>] [storenum <fieldname>]";
01674
01675
01676 if ((argc < 2) || (argc > 13) || ((argc-1) % 2 == 0) ) {
01677 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
01678 return TCL_ERROR;
01679 }
01680
01681
01682 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1], NULL));
01683 if (!sel) {
01684 Tcl_AppendResult(interp, "measure clustsize: invalid atom selection", NULL);
01685 return TCL_ERROR;
01686 }
01687 if (!app->molecule_valid_id(sel->molid())) return MEASURE_ERR_NOMOLECULE;
01688
01689
01690 for (i=2; i<argc; i+=2) {
01691 const char *opt = Tcl_GetStringFromObj(objv[i], NULL);
01692 if (i==(argc-1)) {
01693 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
01694 return TCL_ERROR;
01695 } else if (!strcmp(opt, "cutoff")) {
01696 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &cutoff) != TCL_OK)
01697 return TCL_ERROR;
01698 if (cutoff <= 0.0) {
01699 Tcl_AppendResult(interp, "measure clustsize: invalid 'cutoff' value", NULL);
01700 return TCL_ERROR;
01701 }
01702 } else if (!strcmp(opt, "minsize")) {
01703 if (Tcl_GetIntFromObj(interp, objv[i+1], &minsize) != TCL_OK)
01704 return TCL_ERROR;
01705 if (minsize < 2) {
01706 Tcl_AppendResult(interp, "measure clustsize: invalid 'minsize' value", NULL);
01707 return TCL_ERROR;
01708 }
01709 } else if (!strcmp(opt, "numshared")) {
01710 if (Tcl_GetIntFromObj(interp, objv[i+1], &numshared) != TCL_OK)
01711 return TCL_ERROR;
01712 if (numshared < 0) {
01713 Tcl_AppendResult(interp, "measure clustsize: invalid 'numshared' value", NULL);
01714 return TCL_ERROR;
01715 }
01716 } else if (!strcmp(opt, "usepbc")) {
01717 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &usepbc) != TCL_OK)
01718 return TCL_ERROR;
01719 } else if (!strcmp(opt, "storenum")) {
01720 storenum = Tcl_GetStringFromObj(objv[i+1], NULL);
01721 } else if (!strcmp(opt, "storesize")) {
01722 storesize = Tcl_GetStringFromObj(objv[i+1], NULL);
01723 } else {
01724 Tcl_AppendResult(interp, "unknown keyword '", opt, "'. usage: measure clustsize ", argerrmsg,NULL);
01725 return TCL_ERROR;
01726 }
01727 }
01728
01729 if (usepbc) {
01730 Tcl_AppendResult(interp, "measure clustsize: does not support periodic boundaries yet.", NULL);
01731 return TCL_ERROR;
01732 }
01733
01734
01735
01736
01737 int num_selected=sel->selected;
01738 int *clustersize = new int[num_selected];
01739 int *clusternum= new int [num_selected];
01740 int *clusteridx= new int [num_selected];
01741 for (i=0; i < num_selected; i++) {
01742 clustersize[i] = 0;
01743 clusternum[i] = -1;
01744 clusteridx[i] = -1;
01745 }
01746
01747
01748 rc = measure_clustsize(sel, app->moleculeList, cutoff,
01749 clustersize, clusternum, clusteridx,
01750 minsize, numshared, usepbc);
01751
01752
01753 if (rc != MEASURE_NOERR) {
01754 Tcl_AppendResult(interp, "measure clustsize: error during cluster size analysis calculation.", NULL);
01755 return TCL_ERROR;
01756 }
01757
01758
01759 if (storenum || storesize) {
01760
01761 SymbolTable *atomSelParser = app->atomSelParser;
01762 atomsel_ctxt context(atomSelParser,
01763 app->moleculeList->mol_from_id(sel->molid()),
01764 sel->which_frame, NULL);
01765
01766
01767 if (storenum) {
01768 int fctn = atomSelParser->find_attribute(storenum);
01769 if (fctn >= 0) {
01770 if (atomSelParser->fctns.data(fctn)->returns_a == SymbolTableElement::IS_FLOAT) {
01771 double *tmp_data = new double[sel->num_atoms];
01772 int j=0;
01773 for (int i=0; i<sel->num_atoms; i++) {
01774 if (sel->on[i])
01775 tmp_data[i] = (double) clusternum[j++];
01776 }
01777 atomSelParser->fctns.data(fctn)->set_keyword_double(&context,
01778 sel->num_atoms,
01779 tmp_data, sel->on);
01780 delete[] tmp_data;
01781
01782 } else if (atomSelParser->fctns.data(fctn)->returns_a == SymbolTableElement::IS_INT) {
01783 int *tmp_data = new int[sel->num_atoms];
01784 int j=0;
01785 for (int i=0; i<sel->num_atoms; i++) {
01786 if (sel->on[i])
01787 tmp_data[i] = clusternum[j++];
01788 }
01789 atomSelParser->fctns.data(fctn)->set_keyword_int(&context,
01790 sel->num_atoms,
01791 tmp_data, sel->on);
01792 delete[] tmp_data;
01793 } else {
01794 Tcl_AppendResult(interp, "measure clustsize: storenum field must accept numbers", NULL);
01795 return TCL_ERROR;
01796 }
01797 } else {
01798 Tcl_AppendResult(interp, "measure clustsize: invalid field name for storenum", NULL);
01799 return TCL_ERROR;
01800 }
01801 }
01802
01803
01804 if (storesize) {
01805 int fctn = atomSelParser->find_attribute(storesize);
01806 if (fctn >= 0) {
01807 if (atomSelParser->fctns.data(fctn)->returns_a == SymbolTableElement::IS_FLOAT) {
01808 double *tmp_data = new double[sel->num_atoms];
01809 int j=0;
01810 for (int i=0; i<sel->num_atoms; i++) {
01811 if (sel->on[i])
01812 tmp_data[i] = (double) clustersize[j++];
01813 }
01814 atomSelParser->fctns.data(fctn)->set_keyword_double(&context,
01815 sel->num_atoms,
01816 tmp_data, sel->on);
01817 delete[] tmp_data;
01818
01819 } else if (atomSelParser->fctns.data(fctn)->returns_a == SymbolTableElement::IS_INT) {
01820 int *tmp_data = new int[sel->num_atoms];
01821 int j=0;
01822 for (int i=0; i<sel->num_atoms; i++) {
01823 if (sel->on[i])
01824 tmp_data[i] = clustersize[j++];
01825 }
01826 atomSelParser->fctns.data(fctn)->set_keyword_int(&context,
01827 sel->num_atoms,
01828 tmp_data, sel->on);
01829 delete[] tmp_data;
01830 } else {
01831 Tcl_AppendResult(interp, "measure clustsize: storenum field must accept numbers", NULL);
01832 return TCL_ERROR;
01833 }
01834 } else {
01835 Tcl_AppendResult(interp, "measure clustsize: invalid field name for storesize", NULL);
01836 return TCL_ERROR;
01837 }
01838 }
01839 } else {
01840
01841
01842 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
01843
01844 Tcl_Obj *tcl_ilist = Tcl_NewListObj(0, NULL);
01845 Tcl_Obj *tcl_clist = Tcl_NewListObj(0, NULL);
01846 Tcl_Obj *tcl_nlist = Tcl_NewListObj(0, NULL);
01847 for (i=0; i<num_selected; i++) {
01848 Tcl_ListObjAppendElement(interp, tcl_ilist, Tcl_NewIntObj(clusteridx[i]));
01849 Tcl_ListObjAppendElement(interp, tcl_clist, Tcl_NewIntObj(clustersize[i]));
01850 Tcl_ListObjAppendElement(interp, tcl_nlist, Tcl_NewIntObj(clusternum[i]));
01851 }
01852 Tcl_ListObjAppendElement(interp, tcl_result, tcl_ilist);
01853 Tcl_ListObjAppendElement(interp, tcl_result, tcl_clist);
01854 Tcl_ListObjAppendElement(interp, tcl_result, tcl_nlist);
01855 Tcl_SetObjResult(interp, tcl_result);
01856 }
01857
01858 delete[] clustersize;
01859 delete[] clusternum;
01860 delete[] clusteridx;
01861
01862 return TCL_OK;
01863 }
01864
01865 static int vmd_measure_hbonds(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01866
01867
01868 if (argc != 4 && argc != 5) {
01869 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<cutoff> <angle> <selection1> [<selection2>]");
01870 return TCL_ERROR;
01871 }
01872 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[3],NULL));
01873 if (!sel1) {
01874 Tcl_AppendResult(interp, "measure hbonds: invalid first atom selection", NULL);
01875 return TCL_ERROR;
01876 }
01877
01878 AtomSel *sel2 = NULL;
01879 if (argc == 5) {
01880 sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[4],NULL));
01881 if (!sel2) {
01882 Tcl_AppendResult(interp, "measure hbonds: invalid second atom selection", NULL);
01883 return TCL_ERROR;
01884 }
01885 }
01886 if (sel2 && sel2->molid() != sel1->molid()) {
01887 Tcl_AppendResult(interp, "measure hbonds: error, atom selections must come from same molecule.", NULL);
01888 return TCL_ERROR;
01889 }
01890 double cutoff;
01891 if (Tcl_GetDoubleFromObj(interp, objv[1], &cutoff) != TCL_OK)
01892 return TCL_ERROR;
01893
01894 double maxangle;
01895 if (Tcl_GetDoubleFromObj(interp, objv[2], &maxangle) != TCL_OK)
01896 return TCL_ERROR;
01897
01898 const float *pos = sel1->coordinates(app->moleculeList);
01899 if (!pos) {
01900 Tcl_AppendResult(interp, "measure bondsearch: error, molecule contains no coordinates", NULL);
01901 return TCL_ERROR;
01902 }
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917 Molecule *mol = app->moleculeList->mol_from_id(sel1->molid());
01918
01919 const int *A = sel1->on;
01920 const int *B = sel2 ? sel2->on : sel1->on;
01921
01922 GridSearchPair *pairlist = vmd_gridsearch2(pos, sel1->num_atoms, A, B, (float) cutoff, sel1->num_atoms * 27);
01923 GridSearchPair *p, *tmp;
01924 float donortoH[3], Htoacceptor[3];
01925 Tcl_Obj *donlist = Tcl_NewListObj(0, NULL);
01926 Tcl_Obj *hydlist = Tcl_NewListObj(0, NULL);
01927 Tcl_Obj *acclist = Tcl_NewListObj(0, NULL);
01928 for (p=pairlist; p != NULL; p=tmp) {
01929 MolAtom *a1 = mol->atom(p->ind1);
01930 MolAtom *a2 = mol->atom(p->ind2);
01931
01932
01933 if (mol->atom(p->ind1)->atomType == ATOMHYDROGEN ||
01934 mol->atom(p->ind2)->atomType == ATOMHYDROGEN) {
01935 tmp = p->next;
01936 free(p);
01937 continue;
01938 }
01939 if (!a1->bonded(p->ind2)) {
01940 int b1 = a1->bonds;
01941 int b2 = a2->bonds;
01942 const float *coor1 = pos + 3*p->ind1;
01943 const float *coor2 = pos + 3*p->ind2;
01944 int k;
01945
01946 for (k=0; k<b1; k++) {
01947 const int hindex = a1->bondTo[k];
01948 if (mol->atom(hindex)->atomType == ATOMHYDROGEN) {
01949 const float *hydrogen = pos + 3*hindex;
01950 vec_sub(donortoH,hydrogen,coor1);
01951 vec_sub(Htoacceptor,coor2,hydrogen);
01952 if (angle(donortoH, Htoacceptor) < maxangle ) {
01953 Tcl_ListObjAppendElement(interp, donlist, Tcl_NewIntObj(p->ind1));
01954 Tcl_ListObjAppendElement(interp, acclist, Tcl_NewIntObj(p->ind2));
01955 Tcl_ListObjAppendElement(interp, hydlist, Tcl_NewIntObj(hindex));
01956 }
01957 }
01958 }
01959
01960 if (!sel2) {
01961 for (k=0; k<b2; k++) {
01962 const int hindex = a2->bondTo[k];
01963 if (mol->atom(hindex)->atomType == ATOMHYDROGEN) {
01964 const float *hydrogen = pos + 3*hindex;
01965 vec_sub(donortoH,hydrogen,coor2);
01966 vec_sub(Htoacceptor,coor1,hydrogen);
01967 if (angle(donortoH, Htoacceptor) < maxangle ) {
01968 Tcl_ListObjAppendElement(interp, donlist, Tcl_NewIntObj(p->ind2));
01969 Tcl_ListObjAppendElement(interp, acclist, Tcl_NewIntObj(p->ind1));
01970 Tcl_ListObjAppendElement(interp, hydlist, Tcl_NewIntObj(hindex));
01971 }
01972 }
01973 }
01974 }
01975 }
01976 tmp = p->next;
01977 free(p);
01978 }
01979 Tcl_Obj *result = Tcl_NewListObj(0, NULL);
01980 Tcl_ListObjAppendElement(interp, result, donlist);
01981 Tcl_ListObjAppendElement(interp, result, acclist);
01982 Tcl_ListObjAppendElement(interp, result, hydlist);
01983 Tcl_SetObjResult(interp, result);
01984 return TCL_OK;
01985 }
01986
01987
01988 static int vmd_measure_sasa(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01989
01990 int i;
01991
01992 if (argc < 3) {
01993 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<srad> <sel> [-points <varname>] [-restrict <restrictedsel>] [-samples <numsamples>]");
01994 return TCL_ERROR;
01995 }
01996
01997 Tcl_Obj *ptsvar = NULL;
01998 AtomSel *restrictsel = NULL;
01999 int nsamples = -1;
02000 int *sampleptr = NULL;
02001 for (i=3; i<argc-1; i+=2) {
02002 const char *opt = Tcl_GetStringFromObj(objv[i], NULL);
02003 if (!strcmp(opt, "-points")) {
02004 ptsvar = objv[i+1];
02005 } else if (!strcmp(opt, "-restrict")) {
02006 restrictsel = tcl_commands_get_sel(interp,
02007 Tcl_GetStringFromObj(objv[i+1], NULL));
02008 if (!restrictsel) {
02009 Tcl_AppendResult(interp, "measure sasa: invalid restrict atom selection", NULL);
02010 return TCL_ERROR;
02011 }
02012 } else if (!strcmp(opt, "-samples")) {
02013 if (Tcl_GetIntFromObj(interp, objv[i+1], &nsamples) != TCL_OK)
02014 return TCL_ERROR;
02015 sampleptr = &nsamples;
02016 } else {
02017 Tcl_AppendResult(interp, "measure sasa: unknown option '", opt, "'",
02018 NULL);
02019 return TCL_ERROR;
02020 }
02021 }
02022
02023 double srad;
02024 if (Tcl_GetDoubleFromObj(interp, objv[1], &srad) != TCL_OK)
02025 return TCL_ERROR;
02026 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2],NULL));
02027 if (!sel1) {
02028 Tcl_AppendResult(interp, "measure sasa: invalid first atom selection", NULL);
02029 return TCL_ERROR;
02030 }
02031
02032 const float *pos = sel1->coordinates(app->moleculeList);
02033 if (!pos) {
02034 Tcl_AppendResult(interp, "measure sasa: error, molecule contains no coordinates", NULL);
02035 return TCL_ERROR;
02036 }
02037 Molecule *mol = app->moleculeList->mol_from_id(sel1->molid());
02038 const float *radius = mol->extraflt.data("radius");
02039
02040 ResizeArray<float> sasapts;
02041 float sasa = 0;
02042 int rc = measure_sasa(sel1, pos, radius, (float) srad, &sasa, &sasapts,
02043 restrictsel, sampleptr);
02044 if (rc < 0) {
02045 Tcl_AppendResult(interp, "measure: sasa: ", measure_error(rc), NULL);
02046 return TCL_ERROR;
02047 }
02048 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(sasa));
02049 if (ptsvar) {
02050
02051 Tcl_Obj *listobj = Tcl_NewListObj(0, NULL);
02052 i=0;
02053 while (i<sasapts.num()) {
02054 Tcl_Obj *elem = Tcl_NewListObj(0, NULL);
02055 Tcl_ListObjAppendElement(interp, elem, Tcl_NewDoubleObj(sasapts[i++]));
02056 Tcl_ListObjAppendElement(interp, elem, Tcl_NewDoubleObj(sasapts[i++]));
02057 Tcl_ListObjAppendElement(interp, elem, Tcl_NewDoubleObj(sasapts[i++]));
02058 Tcl_ListObjAppendElement(interp, listobj, elem);
02059 }
02060 Tcl_ObjSetVar2(interp, ptsvar, NULL, listobj, 0);
02061 }
02062 return TCL_OK;
02063 }
02064
02065
02066
02067
02068
02069 static int vmd_measure_energy(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
02070
02071 if (argc<3) {
02072 Tcl_WrongNumArgs(interp, 2, objv-1,
02073 (char *) "bond|angle|dihed|imprp|vdw|elec {{<atomid1> ?<molid1>?} {<atomid2> ?<molid2>?}} ?molid <default molid>? [?frame <frame|all>? | ?first <first>? ?last <last>?]");
02074 return TCL_ERROR;
02075 }
02076
02077 int geomtype, reqatoms;
02078 char *geomname = Tcl_GetStringFromObj(objv[1],NULL);
02079 if (!strncmp(geomname, "bond", 4)) {
02080 reqatoms = 2; geomtype = MEASURE_BOND;
02081 } else if (!strncmp(geomname, "angl", 4)) {
02082 reqatoms = 3; geomtype = MEASURE_ANGLE;
02083 } else if (!strncmp(geomname, "dihe", 4)) {
02084 reqatoms = 4; geomtype = MEASURE_DIHED;
02085 } else if (!strncmp(geomname, "impr", 4)) {
02086 reqatoms = 4; geomtype = MEASURE_IMPRP;
02087 } else if (!strncmp(geomname, "vdw", 3)) {
02088 reqatoms = 2; geomtype = MEASURE_VDW;
02089 } else if (!strncmp(geomname, "elec", 4)) {
02090 reqatoms = 2; geomtype = MEASURE_ELECT;
02091 } else {
02092 Tcl_AppendResult(interp, " measure energy: bad syntax (must specify bond|angle|dihed|imprp|vdw|elec)", NULL);
02093 return TCL_ERROR;
02094 }
02095
02096 int molid[4];
02097 int atmid[4];
02098 int defmolid = -1;
02099 bool allframes = false;
02100 char errstring[200];
02101
02102
02103 int numatms;
02104 Tcl_Obj **data;
02105 if (Tcl_ListObjGetElements(interp, objv[2], &numatms, &data) != TCL_OK) {
02106 Tcl_AppendResult(interp, " measure energy: bad syntax", NULL);
02107 Tcl_AppendResult(interp, " Usage: measure energy bond|angle|dihed|imprp|vdw|elec {{<atomid1> ?<molid1>?} {<atomid2> ?<molid2>?} ...} ?molid <default molid>? [?frame <frame|all>? | ?first <first>? ?last <last>?]", NULL);
02108 return TCL_ERROR;
02109 }
02110
02111 if (numatms!=reqatoms) {
02112 sprintf(errstring, " measure energy %s: must specify exactly %i atoms in list", geomname, reqatoms);
02113 Tcl_AppendResult(interp, errstring, NULL);
02114 return TCL_ERROR;
02115 }
02116
02117 int first=-1, last=-1, frame=-1;
02118 double params[6];
02119 memset(params, 0, 6*sizeof(double));
02120
02121 if (argc>4) {
02122 int i;
02123 for (i=3; i<argc-1; i+=2) {
02124 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
02125 if (!strupncmp(argvcur, "molid", CMDLEN)) {
02126 if (Tcl_GetIntFromObj(interp, objv[i+1], &defmolid) != TCL_OK) {
02127 Tcl_AppendResult(interp, " measure energy: bad molid", NULL);
02128 return TCL_ERROR;
02129 }
02130 } else if (!strupncmp(argvcur, "k", CMDLEN)) {
02131 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params) != TCL_OK) {
02132 Tcl_AppendResult(interp, " measure energy: bad force constant value", NULL);
02133 return TCL_ERROR;
02134 }
02135 } else if (!strupncmp(argvcur, "x0", CMDLEN)) {
02136 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+1) != TCL_OK) {
02137 Tcl_AppendResult(interp, " measure energy: bad equilibrium value", NULL);
02138 return TCL_ERROR;
02139 }
02140 } else if (!strupncmp(argvcur, "kub", CMDLEN)) {
02141 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+2) != TCL_OK) {
02142 Tcl_AppendResult(interp, " measure energy: bad Urey-Bradley force constant value", NULL);
02143 return TCL_ERROR;
02144 }
02145 } else if (!strupncmp(argvcur, "s0", CMDLEN)) {
02146 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+3) != TCL_OK) {
02147 Tcl_AppendResult(interp, " measure energy: bad Urey-Bradley equilibrium distance", NULL);
02148 return TCL_ERROR;
02149 }
02150 } else if (!strupncmp(argvcur, "n", CMDLEN)) {
02151 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+1) != TCL_OK) {
02152 Tcl_AppendResult(interp, " measure energy: bad dihedral periodicity", NULL);
02153 return TCL_ERROR;
02154 }
02155 } else if (!strupncmp(argvcur, "delta", CMDLEN)) {
02156 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+2) != TCL_OK) {
02157 Tcl_AppendResult(interp, " measure energy: bad dihedral phase shift", NULL);
02158 return TCL_ERROR;
02159 }
02160 } else if (!strupncmp(argvcur, "eps1", CMDLEN)) {
02161 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params) != TCL_OK) {
02162 Tcl_AppendResult(interp, " measure energy: bad vdw well depth", NULL);
02163 return TCL_ERROR;
02164 }
02165 } else if (!strupncmp(argvcur, "rmin1", CMDLEN)) {
02166 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+1) != TCL_OK) {
02167 Tcl_AppendResult(interp, " measure energy: bad vdw equilibrium distance", NULL);
02168 return TCL_ERROR;
02169 }
02170 } else if (!strupncmp(argvcur, "eps2", CMDLEN)) {
02171 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+2) != TCL_OK) {
02172 Tcl_AppendResult(interp, " measure energy: bad vdw well depth", NULL);
02173 return TCL_ERROR;
02174 }
02175 } else if (!strupncmp(argvcur, "rmin2", CMDLEN)) {
02176 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+3) != TCL_OK) {
02177 Tcl_AppendResult(interp, " measure energy: bad vdw equilibrium distance", NULL);
02178 return TCL_ERROR;
02179 }
02180 } else if (!strupncmp(argvcur, "q1", CMDLEN)) {
02181 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params) != TCL_OK) {
02182 Tcl_AppendResult(interp, " measure energy: bad charge value", NULL);
02183 return TCL_ERROR;
02184 }
02185 params[2]=1.0;
02186 } else if (!strupncmp(argvcur, "q2", CMDLEN)) {
02187 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+1) != TCL_OK) {
02188 Tcl_AppendResult(interp, " measure energy: bad charge value", NULL);
02189 return TCL_ERROR;
02190 }
02191 params[3]=1.0;
02192 } else if (!strupncmp(argvcur, "cutoff", CMDLEN)) {
02193 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+4) != TCL_OK) {
02194 Tcl_AppendResult(interp, " measure energy: bad electrostatic cutoff value", NULL);
02195 return TCL_ERROR;
02196 }
02197 } else if (!strupncmp(argvcur, "switchdist", CMDLEN)) {
02198 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+5) != TCL_OK) {
02199 Tcl_AppendResult(interp, " measure energy: bad switching distance value", NULL);
02200 return TCL_ERROR;
02201 }
02202 } else if (!strupncmp(argvcur, "first", CMDLEN)) {
02203 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
02204 Tcl_AppendResult(interp, " measure energy: bad first frame value", NULL);
02205 return TCL_ERROR;
02206 }
02207 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
02208 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
02209 Tcl_AppendResult(interp, " measure energy: bad last frame value", NULL);
02210 return TCL_ERROR;
02211 }
02212 } else if (!strupncmp(argvcur, "frame", CMDLEN)) {
02213 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "all")) {
02214 allframes = true;
02215 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &frame) != TCL_OK) {
02216 Tcl_AppendResult(interp, " measure energy: bad frame value", NULL);
02217 return TCL_ERROR;
02218 }
02219 } else {
02220 Tcl_AppendResult(interp, " measure energy: invalid syntax, no such keyword: ", argvcur, NULL);
02221 return TCL_ERROR;
02222 }
02223 }
02224 }
02225
02226 if ((allframes || frame>=0) && (first>=0 || last>=0)) {
02227 Tcl_AppendResult(interp, "measure energy: Ambiguous syntax: You cannot specify a frame AND a frame range (using first or last).", NULL);
02228 Tcl_AppendResult(interp, "\nUsage:\nmeasure bond <molid1>/<atomid1> <molid2>/<atomid2> [?frame <frame|all>? | ?first <first>? ?last <last>?]", NULL);
02229 return TCL_ERROR;
02230 }
02231
02232 if (allframes) first=0;
02233
02234
02235 if (defmolid<0) defmolid = app->molecule_top();
02236
02237
02238 int i,numelem;
02239 Tcl_Obj **atmmol;
02240 for (i=0; i<numatms; i++) {
02241 if (Tcl_ListObjGetElements(interp, data[i], &numelem, &atmmol) != TCL_OK) {
02242 return TCL_ERROR;
02243 }
02244
02245 if (Tcl_GetIntFromObj(interp, atmmol[0], atmid+i) != TCL_OK) {
02246 Tcl_AppendResult(interp, " measure energy: bad atom index", NULL);
02247 return TCL_ERROR;
02248 }
02249
02250 if (numelem==2) {
02251 if (Tcl_GetIntFromObj(interp, atmmol[1], molid+i) != TCL_OK) {
02252 Tcl_AppendResult(interp, " measure energy: bad molid", NULL);
02253 return TCL_ERROR;
02254 }
02255 } else molid[i] = defmolid;
02256 }
02257
02258
02259
02260 ResizeArray<float> gValues(1024);
02261 int ret_val;
02262 ret_val = measure_energy(app->moleculeList, molid, atmid, reqatoms, &gValues, frame, first, last,
02263 defmolid, params, geomtype);
02264 if (ret_val<0) {
02265 printf("ERROR\n %s\n", measure_error(ret_val));
02266 Tcl_AppendResult(interp, measure_error(ret_val), NULL);
02267 return TCL_ERROR;
02268 }
02269
02270 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
02271 int numvalues = gValues.num();
02272 for (int count = 0; count < numvalues; count++) {
02273 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(gValues[count]));
02274 }
02275 Tcl_SetObjResult(interp, tcl_result);
02276
02277 return TCL_OK;
02278 }
02279
02280
02281
02282
02283
02284 static int vmd_measure_surface(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
02285 if (argc!=5) {
02286 Tcl_WrongNumArgs(interp, 2, objv-1,
02287 (char *) "<sel> <gridsize> <radius> <depth>");
02288 return TCL_ERROR;
02289 }
02290
02291 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
02292 if (!sel) {
02293 Tcl_AppendResult(interp, "measure surface: no atom selection", NULL);
02294 return TCL_ERROR;
02295 }
02296
02297 const float *framepos = sel->coordinates(app->moleculeList);
02298 if (!framepos) return TCL_ERROR;
02299
02300 double gridsz;
02301 if (Tcl_GetDoubleFromObj(interp, objv[2], &gridsz) != TCL_OK)
02302 return TCL_ERROR;
02303
02304 double radius;
02305 if (Tcl_GetDoubleFromObj(interp, objv[3], &radius) != TCL_OK)
02306 return TCL_ERROR;
02307
02308 double depth;
02309 if (Tcl_GetDoubleFromObj(interp, objv[4], &depth) != TCL_OK)
02310 return TCL_ERROR;
02311
02312 int *surface;
02313 int n_surf;
02314
02315 int ret_val = measure_surface(sel, app->moleculeList, framepos,
02316 gridsz, radius, depth, &surface, &n_surf);
02317 if (ret_val < 0) {
02318 Tcl_AppendResult(interp, "measure surface: ", measure_error(ret_val));
02319 return TCL_ERROR;
02320 }
02321
02322 Tcl_Obj *surf_list = Tcl_NewListObj(0, NULL);
02323
02324 int i;
02325 for(i=0; i < n_surf; i++) {
02326 Tcl_ListObjAppendElement(interp, surf_list, Tcl_NewIntObj(surface[i]));
02327 }
02328 Tcl_SetObjResult(interp, surf_list);
02329 delete [] surface;
02330
02331 return TCL_OK;
02332 }
02333
02334
02335
02336
02337
02338 static int vmd_measure_pbc2onc_transform(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
02339 if (argc < 2) {
02340 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<center> [molid <default>] [frame <frame|last>]");
02341 return TCL_ERROR;
02342 }
02343
02344
02345 int ndim;
02346 Tcl_Obj **centerObj;
02347 if (Tcl_ListObjGetElements(interp, objv[1], &ndim, ¢erObj) != TCL_OK) {
02348 Tcl_AppendResult(interp, " measure pbc2onc: bad syntax", NULL);
02349 Tcl_AppendResult(interp, " Usage: measure pbc2onc <center> [molid <default>] [frame <frame|last>]", NULL);
02350 return TCL_ERROR;
02351 }
02352
02353 if (ndim!=3) {
02354 Tcl_AppendResult(interp, " measure pbc2onc: need three numbers for a vector", NULL);
02355 return TCL_ERROR;
02356 }
02357
02358 int i;
02359 double tmp;
02360 float center[3];
02361 for (i=0; i<3; i++) {
02362 if (Tcl_GetDoubleFromObj(interp, centerObj[i], &tmp) != TCL_OK) {
02363 Tcl_AppendResult(interp, " measure pbc2onc: non-numeric in center", NULL);
02364 return TCL_ERROR;
02365 }
02366 center[i] = (float)tmp;
02367 }
02368
02369 int molid = app->molecule_top();
02370 int frame = -2;
02371 if (argc>3) {
02372 for (i=2; i<argc; i+=2) {
02373 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
02374 if (!strupncmp(argvcur, "molid", CMDLEN)) {
02375 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "top")) {
02376
02377 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &molid) != TCL_OK) {
02378 Tcl_AppendResult(interp, " measure pbc2onc: bad molid", NULL);
02379 return TCL_ERROR;
02380 }
02381 } else if (!strupncmp(argvcur, "frame", CMDLEN)) {
02382 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "last")) {
02383 frame=-1;
02384 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &frame) != TCL_OK) {
02385 Tcl_AppendResult(interp, " measure pbc2onc: bad frame value", NULL);
02386 return TCL_ERROR;
02387 }
02388 } else {
02389 Tcl_AppendResult(interp, " measure pbc2onc: invalid syntax, no such keyword: ", argvcur, NULL);
02390 return TCL_ERROR;
02391 }
02392 }
02393 }
02394
02395
02396 Matrix4 transform;
02397 int ret_val = measure_pbc2onc(app->moleculeList, molid, frame, center, transform);
02398 if (ret_val < 0) {
02399 Tcl_AppendResult(interp, "measure pbc2onc: ", measure_error(ret_val), NULL);
02400 return TCL_ERROR;
02401 }
02402
02403 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
02404 for (i=0; i<4; i++) {
02405 Tcl_Obj *rowListObj = Tcl_NewListObj(0, NULL);
02406 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(transform.mat[i+0]));
02407 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(transform.mat[i+4]));
02408 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(transform.mat[i+8]));
02409 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(transform.mat[i+12]));
02410 Tcl_ListObjAppendElement(interp, tcl_result, rowListObj);
02411 }
02412 Tcl_SetObjResult(interp, tcl_result);
02413
02414 return TCL_OK;
02415 }
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447 static int vmd_measure_pbc_neighbors(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
02448 if (argc < 3) {
02449 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<center> <cutoff> ?sel <selection>? ?align <matrix>? ?molid <default>? ?frame <frame|last>? ?boundingbox PBC|{<mincoord> <maxcoord>}?");
02450 return TCL_ERROR;
02451 }
02452
02453
02454 int ndim;
02455 Tcl_Obj **centerObj;
02456 if (Tcl_ListObjGetElements(interp, objv[1], &ndim, ¢erObj) != TCL_OK) {
02457 Tcl_AppendResult(interp, " measure pbcneighbors: bad syntax", NULL);
02458 Tcl_AppendResult(interp, " Usage: measure pbcneighbors <center> <cutoff> [<sel <sel>] [align <matrix>] [molid <default>] [frame <frame|last>] [boundingbox <PBC|{<mincoord> <maxcoord>}>]", NULL);
02459 return TCL_ERROR;
02460 }
02461
02462 if (ndim!=3) {
02463 Tcl_AppendResult(interp, " measure pbcneighbors: need three numbers for a vector", NULL);
02464 return TCL_ERROR;
02465 }
02466
02467 int i;
02468 double tmp;
02469 float center[3];
02470 for (i=0; i<3; i++) {
02471 if (Tcl_GetDoubleFromObj(interp, centerObj[i], &tmp) != TCL_OK) {
02472 Tcl_AppendResult(interp, " measure pbcneighbors: non-numeric in center", NULL);
02473 return TCL_ERROR;
02474 }
02475 center[i] = float(tmp);
02476 }
02477
02478
02479 Tcl_Obj **cutoffObj;
02480 if (Tcl_ListObjGetElements(interp, objv[2], &ndim, &cutoffObj) != TCL_OK) {
02481 Tcl_AppendResult(interp, " measure pbcneighbors: bad syntax", NULL);
02482 Tcl_AppendResult(interp, " Usage: measure pbcneighbors <center> <cutoff> [<sel <sel>] [align <matrix>] [molid <default>] [frame <frame|last>] [boundingbox <PBC|{<mincoord> <maxcoord>}>]", NULL);
02483 return TCL_ERROR;
02484 }
02485
02486 if (ndim!=3 && ndim!=1) {
02487 Tcl_AppendResult(interp, " measure pbcneighbors: need either one or three numbers for cutoff", NULL);
02488 return TCL_ERROR;
02489 }
02490
02491 float cutoff[3];
02492 for (i=0; i<ndim; i++) {
02493 if (Tcl_GetDoubleFromObj(interp, cutoffObj[i], &tmp) != TCL_OK) {
02494 Tcl_AppendResult(interp, " measure pbcneighbors: non-numeric in cutoff", NULL);
02495 return TCL_ERROR;
02496 }
02497 cutoff[i] = float(tmp);
02498 }
02499
02500 if (ndim==1) { cutoff[2] = cutoff[1] = cutoff[0]; }
02501
02502 bool molidprovided=0;
02503 float *boxminmax=NULL;
02504 int molid = app->molecule_top();
02505 int frame = -2;
02506 AtomSel *sel = NULL;
02507 Matrix4 alignment;
02508 if (argc>4) {
02509 for (i=3; i<argc; i+=2) {
02510 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
02511 if (!strupncmp(argvcur, "sel", CMDLEN)) {
02512
02513 sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[i+1],NULL));
02514 if (!sel) {
02515 Tcl_AppendResult(interp, "measure pbcneighbors: invalid atom selection", NULL);
02516 return TCL_ERROR;
02517 }
02518 if (!app->molecule_valid_id(sel->molid())) {
02519 Tcl_AppendResult(interp, "measure pbcneighbors: ",
02520 measure_error(MEASURE_ERR_NOMOLECULE), NULL);
02521 return TCL_ERROR;
02522 }
02523 if (!sel->selected) {
02524 Tcl_AppendResult(interp, "measure pbcneighbors: selection contains no atoms.", NULL);
02525 return TCL_ERROR;
02526 }
02527 } else if (!strupncmp(argvcur, "molid", CMDLEN)) {
02528 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "top")) {
02529
02530 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &molid) != TCL_OK) {
02531 Tcl_AppendResult(interp, " measure pbcneighbors: bad molid", NULL);
02532 return TCL_ERROR;
02533 }
02534 molidprovided = 1;
02535 } else if (!strupncmp(argvcur, "frame", CMDLEN)) {
02536 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "last")) {
02537 frame=-1;
02538 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &frame) != TCL_OK) {
02539 Tcl_AppendResult(interp, " measure pbcneighbors: bad frame value", NULL);
02540 return TCL_ERROR;
02541 }
02542 } else if (!strupncmp(argvcur, "align", CMDLEN)) {
02543
02544 if (tcl_get_matrix("measure pbcneighbors: ", interp, objv[i+1], alignment.mat) != TCL_OK) {
02545 return TCL_ERROR;
02546 }
02547 } else if (!strupncmp(argvcur, "boundingbox", CMDLEN)) {
02548
02549
02550 char *argv2 = Tcl_GetStringFromObj(objv[i+1],NULL);
02551 if (!strupncmp(argv2, "on", CMDLEN) || !strupncmp(argv2, "pbc", CMDLEN)) {
02552 boxminmax = new float[6];
02553 compute_pbcminmax(app->moleculeList, molid, frame, center, &alignment,
02554 boxminmax, boxminmax+3);
02555 } else {
02556
02557 int j, k, ncoor;
02558 Tcl_Obj **boxListObj;
02559 if (Tcl_ListObjGetElements(interp, objv[i+1], &ncoor, &boxListObj) != TCL_OK) {
02560 Tcl_AppendResult(interp, " measure pbcneighbors: invalid bounding box parameter", NULL);
02561 return TCL_ERROR;
02562 }
02563 if (ncoor!=2) {
02564 Tcl_AppendResult(interp, " measure pbcneighbors: need 2 points for bounding box", NULL);
02565 return TCL_ERROR;
02566 }
02567 int ndim = 0;
02568 double tmp;
02569 Tcl_Obj **boxObj;
02570 boxminmax = new float[6];
02571 for (j=0; j<2; j++) {
02572 if (Tcl_ListObjGetElements(interp, boxListObj[j], &ndim, &boxObj) != TCL_OK) {
02573 Tcl_AppendResult(interp, " measure pbcneighbors: bad syntax in boundingbox", NULL);
02574 return TCL_ERROR;
02575 }
02576
02577 for (k=0; k<3; k++) {
02578 if (Tcl_GetDoubleFromObj(interp, boxObj[k], &tmp) != TCL_OK) {
02579 Tcl_AppendResult(interp, " measure pbcneighbors: non-numeric in boundingbox", NULL);
02580 return TCL_ERROR;
02581 }
02582 boxminmax[3*j+k] = (float)tmp;
02583 }
02584 }
02585 }
02586
02587 } else {
02588 Tcl_AppendResult(interp, " measure pbcneighbors: invalid syntax, no such keyword: ", argvcur, NULL);
02589 return TCL_ERROR;
02590 }
02591 }
02592 }
02593
02594
02595
02596 if (sel && !molidprovided) {
02597 molid = sel->molid();
02598 }
02599
02600 ResizeArray<float> extcoord_array;
02601 ResizeArray<int> indexmap_array;
02602
02603 int ret_val = measure_pbc_neighbors(app->moleculeList, sel, molid, frame, &alignment, center, cutoff,
02604 boxminmax, &extcoord_array, &indexmap_array);
02605 delete [] boxminmax;
02606
02607 if (ret_val < 0) {
02608 Tcl_AppendResult(interp, "measure pbcneighbors: ", measure_error(ret_val), NULL);
02609 return TCL_ERROR;
02610 }
02611 printf("measure pbcneighbors: %i neighbor atoms found\n", indexmap_array.num());
02612
02613 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
02614 Tcl_Obj *coorListObj = Tcl_NewListObj(0, NULL);
02615 Tcl_Obj *indexListObj = Tcl_NewListObj(0, NULL);
02616 for (i=0; i<indexmap_array.num(); i++) {
02617 Tcl_Obj *rowListObj = Tcl_NewListObj(0, NULL);
02618 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(extcoord_array[3*i]));
02619 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(extcoord_array[3*i+1]));
02620 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(extcoord_array[3*i+2]));
02621 Tcl_ListObjAppendElement(interp, coorListObj, rowListObj);
02622 Tcl_ListObjAppendElement(interp, indexListObj, Tcl_NewIntObj(indexmap_array[i]));
02623 }
02624 Tcl_ListObjAppendElement(interp, tcl_result, coorListObj);
02625 Tcl_ListObjAppendElement(interp, tcl_result, indexListObj);
02626 Tcl_SetObjResult(interp, tcl_result);
02627
02628 return TCL_OK;
02629 }
02630
02631
02632
02633
02634
02635
02636
02637
02638 static int vmd_measure_inertia(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
02639 bool moments = FALSE;
02640 bool eigenvals = FALSE;
02641 if (argc < 2 || argc > 4) {
02642 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<selection> [moments] [eigenvals]");
02643 return TCL_ERROR;
02644 }
02645 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
02646 if (!sel) {
02647 Tcl_AppendResult(interp, "measure inertia: no atom selection", NULL);
02648 return TCL_ERROR;
02649 }
02650
02651 if (!app->molecule_valid_id(sel->molid())) {
02652 Tcl_AppendResult(interp, "measure inertia: ",
02653 measure_error(MEASURE_ERR_NOMOLECULE), NULL);
02654 return TCL_ERROR;
02655 }
02656
02657 if (argc>2) {
02658 int i;
02659 for (i=2; i<argc; i++) {
02660 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
02661
02662 if (argvcur[0]=='-') argvcur++;
02663
02664 if (!strupncmp(argvcur, "moments", CMDLEN)) {
02665 moments = TRUE;
02666 }
02667 else if (!strupncmp(argvcur, "eigenvals", CMDLEN)) {
02668 eigenvals = TRUE;
02669 }
02670 else {
02671 Tcl_AppendResult(interp, " measure inertia: unrecognized option\n", NULL);
02672 Tcl_AppendResult(interp, " Usage: measure inertia <selection> [moments] [eigenvals]", NULL);
02673 return TCL_ERROR;
02674 }
02675 }
02676 }
02677
02678 float priaxes[3][3];
02679 float itensor[4][4];
02680 float evalue[3], rcom[3];
02681 int ret_val = measure_inertia(sel, app->moleculeList, NULL, rcom, priaxes, itensor, evalue);
02682 if (ret_val < 0) {
02683 Tcl_AppendResult(interp, "measure inertia: ", measure_error(ret_val), NULL);
02684 return TCL_ERROR;
02685 }
02686
02687
02688 int i;
02689 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
02690
02691 Tcl_Obj *rcomObj = Tcl_NewListObj(0, NULL);
02692 Tcl_ListObjAppendElement(interp, rcomObj, Tcl_NewDoubleObj(rcom[0]));
02693 Tcl_ListObjAppendElement(interp, rcomObj, Tcl_NewDoubleObj(rcom[1]));
02694 Tcl_ListObjAppendElement(interp, rcomObj, Tcl_NewDoubleObj(rcom[2]));
02695 Tcl_ListObjAppendElement(interp, tcl_result, rcomObj);
02696
02697 Tcl_Obj *axesListObj = Tcl_NewListObj(0, NULL);
02698 for (i=0; i<3; i++) {
02699 Tcl_Obj *axesObj = Tcl_NewListObj(0, NULL);
02700 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(priaxes[i][0]));
02701 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(priaxes[i][1]));
02702 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(priaxes[i][2]));
02703 Tcl_ListObjAppendElement(interp, axesListObj, axesObj);
02704 }
02705 Tcl_ListObjAppendElement(interp, tcl_result, axesListObj);
02706
02707 if (moments) {
02708 Tcl_Obj *momListObj = Tcl_NewListObj(0, NULL);
02709 for (i=0; i<3; i++) {
02710 Tcl_Obj *momObj = Tcl_NewListObj(0, NULL);
02711 Tcl_ListObjAppendElement(interp, momObj, Tcl_NewDoubleObj(itensor[i][0]));
02712 Tcl_ListObjAppendElement(interp, momObj, Tcl_NewDoubleObj(itensor[i][1]));
02713 Tcl_ListObjAppendElement(interp, momObj, Tcl_NewDoubleObj(itensor[i][2]));
02714 Tcl_ListObjAppendElement(interp, momListObj, momObj);
02715 }
02716 Tcl_ListObjAppendElement(interp, tcl_result, momListObj);
02717 }
02718
02719 if (eigenvals) {
02720 Tcl_Obj *eigvListObj = Tcl_NewListObj(0, NULL);
02721 Tcl_ListObjAppendElement(interp, eigvListObj, Tcl_NewDoubleObj(evalue[0]));
02722 Tcl_ListObjAppendElement(interp, eigvListObj, Tcl_NewDoubleObj(evalue[1]));
02723 Tcl_ListObjAppendElement(interp, eigvListObj, Tcl_NewDoubleObj(evalue[2]));
02724 Tcl_ListObjAppendElement(interp, tcl_result, eigvListObj);
02725 }
02726 Tcl_SetObjResult(interp, tcl_result);
02727
02728 return TCL_OK;
02729 }
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821 static int vmd_measure_symmetry(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
02822 if (argc<2) {
02823 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> [element [<vector>]] [-tol <value>] [-nobonds] [-verbose <level>]");
02824 return TCL_ERROR;
02825 }
02826 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
02827 if (!sel) {
02828 Tcl_AppendResult(interp, "measure symmetry: no atom selection", NULL);
02829 return TCL_ERROR;
02830 }
02831 if (!app->molecule_valid_id(sel->molid())) {
02832 Tcl_AppendResult(interp, "measure symmetry: ",
02833 measure_error(MEASURE_ERR_NOMOLECULE), NULL);
02834 return TCL_ERROR;
02835 }
02836
02837 double sigma = 0.1;
02838 float axis[3];
02839 int checkelement = 0;
02840 int checkbonds = 1;
02841 int order = 0;
02842 int verbose = 1;
02843 int impose = 0;
02844 int imposeinvers = 0;
02845 int numimposeplan = 0;
02846 int numimposeaxes = 0;
02847 int numimposerref = 0;
02848 float *imposeplan = NULL;
02849 float *imposeaxes = NULL;
02850 float *imposerref = NULL;
02851 int *imposeaxesord = NULL;
02852 int *imposerreford = NULL;
02853 AtomSel *idealsel = NULL;
02854
02855 if (argc>2) {
02856 int bailout = 0;
02857 int i;
02858 for (i=2; (i<argc && !bailout); i++) {
02859 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
02860
02861 if (argvcur[0]=='-') argvcur++;
02862
02863 if (!strupncmp(argvcur, "tol", CMDLEN)) {
02864 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &sigma) != TCL_OK) {
02865 Tcl_AppendResult(interp, " measure symmetry: bad tolerance value", NULL);
02866 bailout = 1; continue;
02867 }
02868 i++;
02869 }
02870 else if (!strupncmp(argvcur, "verbose", CMDLEN)) {
02871 if (Tcl_GetIntFromObj(interp, objv[i+1], &verbose) != TCL_OK) {
02872 Tcl_AppendResult(interp, " measure symmetry: bad verbosity level value", NULL);
02873 bailout = 1; continue;
02874 }
02875 i++;
02876 }
02877 else if (!strupncmp(argvcur, "nobonds", CMDLEN)) {
02878 checkbonds = 0;
02879 }
02880 else if (!strupcmp(argvcur, "I")) {
02881 checkelement = 1;
02882 }
02883 else if (!strupncmp(argvcur, "plane", CMDLEN)) {
02884 if (tcl_get_vector(Tcl_GetStringFromObj(objv[i+1],NULL), axis, interp)!=TCL_OK) {
02885 bailout = 1; continue;
02886 }
02887 checkelement = 2;
02888 i++;
02889 }
02890 else if (!strupncmp(argvcur, "C", 1) || !strupncmp(argvcur, "S", 1)) {
02891 char *begptr = argvcur+1;
02892 char *endptr;
02893 order = strtol(begptr, &endptr, 10);
02894 if (endptr==begptr || *endptr!='\0') {
02895 Tcl_AppendResult(interp, " measure symmetry: bad symmetry element format (must be I, C*, S*, plane, where * is the order). ", NULL);
02896 bailout = 1; continue;
02897 }
02898
02899 if (tcl_get_vector(Tcl_GetStringFromObj(objv[i+1],NULL), axis, interp)!=TCL_OK) {
02900 bailout = 1; continue;
02901 }
02902
02903 if (!strupncmp(argvcur, "C", 1)) checkelement = 3;
02904 if (!strupncmp(argvcur, "S", 1)) checkelement = 4;
02905 i++;
02906 }
02907 else if (!strupncmp(argvcur, "idealsel", CMDLEN)) {
02908 idealsel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[i+1],NULL));
02909 if (!sel) {
02910 Tcl_AppendResult(interp, "measure symmetry: no atom selection for idealized coordinates", NULL);
02911 bailout = 1; continue;
02912 }
02913 if (idealsel->molid()!=sel->molid()) {
02914 Tcl_AppendResult(interp, "measure symmetry: selection and idealsel must be from the same molecule", NULL);
02915 bailout = 1; continue;
02916 }
02917 if (idealsel->selected<sel->selected) {
02918 Tcl_AppendResult(interp, "measure symmetry: selection must be a subset of idealsel", NULL);
02919 bailout = 1; continue;
02920 }
02921
02922 int j;
02923 for (j=0; j<sel->num_atoms; j++) {
02924 if (sel->on[j] && !idealsel->on[j]) {
02925 Tcl_AppendResult(interp, "measure symmetry: selection must be a subset of idealsel", NULL);
02926 bailout = 1; continue;
02927 }
02928 }
02929
02930 i++;
02931 }
02932 else if (!strupncmp(argvcur, "imposeinversion", CMDLEN)) {
02933 imposeinvers = 1;
02934 impose = 1;
02935 }
02936 else if (!strupncmp(argvcur, "imposeplanes", CMDLEN)) {
02937
02938 int nelem;
02939 Tcl_Obj **elemListObj;
02940 if (i+1>=argc ||
02941 Tcl_ListObjGetElements(interp, objv[i+1], &nelem, &elemListObj) != TCL_OK) {
02942 Tcl_AppendResult(interp, " measure symmetry: bad syntax for imposeplanes option", NULL);
02943 bailout = 1; continue;
02944 }
02945 float *elem = new float[3*nelem];
02946 int k;
02947 for (k=0; k<nelem; k++) {
02948 int nobj;
02949 Tcl_Obj **vecObj;
02950 if (Tcl_ListObjGetElements(interp, elemListObj[k], &nobj, &vecObj) != TCL_OK) {
02951 delete [] elem;
02952 Tcl_AppendResult(interp, " measure symmetry: bad syntax for imposeplanes option", NULL);
02953 bailout = 1; continue;
02954 }
02955 if (nobj!=3) {
02956 delete [] elem;
02957 Tcl_AppendResult(interp, " measure symmetry imposeplanes: vector must have 3 elements", NULL);
02958 bailout = 1; continue;
02959 }
02960
02961 int m;
02962 for (m=0; m<3; m++) {
02963 double d;
02964 if (Tcl_GetDoubleFromObj(interp, vecObj[m], &d) != TCL_OK) {
02965 delete [] elem;
02966 bailout = 1; continue;
02967 }
02968 elem[3*k+m] = (float)d;
02969 }
02970 }
02971 if (imposeplan) delete [] imposeplan;
02972 imposeplan = elem;
02973 numimposeplan = nelem;
02974 impose = 1;
02975 i++;
02976 }
02977 else if (!strupncmp(argvcur, "imposeaxes", CMDLEN) ||
02978 !strupncmp(argvcur, "imposerotref", CMDLEN)) {
02979
02980 int nelem;
02981 Tcl_Obj **elemListObj;
02982 if (i+1>=argc ||
02983 Tcl_ListObjGetElements(interp, objv[i+1], &nelem, &elemListObj) != TCL_OK ||
02984 nelem%2) {
02985 Tcl_AppendResult(interp, " measure symmetry: bad syntax for imposeaxes/imposerotref option", NULL);
02986 bailout = 1; continue;
02987 }
02988 nelem /= 2;
02989
02990 if (nelem<=0) {
02991 i++;
02992 continue;
02993 }
02994 float *elem = new float[3*nelem];
02995 int *axorder = new int[nelem];
02996 int k;
02997 for (k=0; k<nelem; k++) {
02998 int nobj;
02999 Tcl_Obj **vecObj;
03000 if (Tcl_ListObjGetElements(interp, elemListObj[2*k], &nobj, &vecObj) != TCL_OK) {
03001 delete [] elem;
03002 delete [] axorder;
03003 Tcl_AppendResult(interp, " measure symmetry impose: bad syntax for axis vector", NULL);
03004 bailout = 1; continue;
03005 }
03006 if (Tcl_GetIntFromObj(interp, elemListObj[2*k+1], &axorder[k]) != TCL_OK) {
03007 delete [] elem;
03008 delete [] axorder;
03009 bailout = 1; continue;
03010 }
03011 if (nobj!=3) {
03012 delete [] elem;
03013 delete [] axorder;
03014 Tcl_AppendResult(interp, " measure symmetry impose: axis vector must have 3 elements", NULL);
03015 bailout = 1; continue;
03016 }
03017
03018 int m;
03019 for (m=0; m<3; m++) {
03020 double d;
03021 if (Tcl_GetDoubleFromObj(interp, vecObj[m], &d) != TCL_OK) {
03022 delete [] elem;
03023 delete [] axorder;
03024 bailout = 1; continue;
03025 }
03026 elem[3*k+m] = (float)d;
03027 }
03028 }
03029 if (!strupncmp(argvcur, "imposeaxes", CMDLEN)) {
03030 if (imposeaxes) delete [] imposeaxes;
03031 if (imposeaxesord) delete [] imposeaxesord;
03032 imposeaxes = elem;
03033 imposeaxesord = axorder;
03034 numimposeaxes = nelem;
03035 } else if (!strupncmp(argvcur, "imposerotref", CMDLEN)) {
03036 if (imposerref) delete [] imposerref;
03037 if (imposerreford) delete [] imposerreford;
03038 imposerref = elem;
03039 imposerreford = axorder;
03040 numimposerref = nelem;
03041 }
03042
03043 impose = 1;
03044 i++;
03045 }
03046 else {
03047 Tcl_AppendResult(interp, " measure symmetry: unrecognized option ", NULL);
03048 Tcl_AppendResult(interp, argvcur);
03049 Tcl_AppendResult(interp, ".\n Usage: measure symmetry <selection> [element [<vector>]] [-tol <value>] [-nobonds] [-verbose <level>]", NULL);
03050 bailout = 1; continue;
03051 }
03052 }
03053
03054 if (bailout) {
03055 if (imposeplan) delete [] imposeplan;
03056 if (imposeaxes) delete [] imposeaxes;
03057 if (imposerref) delete [] imposerref;
03058 if (imposeaxesord) delete [] imposeaxesord;
03059 if (imposerreford) delete [] imposerreford;
03060 return TCL_ERROR;
03061 }
03062 }
03063
03064
03065 Symmetry sym = Symmetry(sel, app->moleculeList, verbose);
03066
03067
03068 sym.set_overlaptol(float(sigma));
03069
03070
03071 sym.set_checkbonds(checkbonds);
03072
03073 if (checkelement) {
03074
03075
03076 float overlap = 0.0;
03077 if (checkelement==1) {
03078 overlap = sym.score_inversion();
03079 }
03080 else if (checkelement==2) {
03081 overlap = sym.score_plane(axis);
03082 }
03083 else if (checkelement==3) {
03084 overlap = sym.score_axis(axis, order);
03085 }
03086 else if (checkelement==4) {
03087 overlap = sym.score_rotary_reflection(axis, order);
03088 }
03089
03090 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
03091 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(overlap));
03092 Tcl_SetObjResult(interp, tcl_result);
03093 return TCL_OK;
03094 }
03095
03096 if (impose) {
03097 sym.impose(imposeinvers, numimposeplan, imposeplan,
03098 numimposeaxes, imposeaxes, imposeaxesord,
03099 numimposerref, imposerref, imposerreford);
03100 if (imposeplan) delete [] imposeplan;
03101 if (imposeaxes) delete [] imposeaxes;
03102 if (imposerref) delete [] imposerref;
03103 if (imposeaxesord) delete [] imposeaxesord;
03104 if (imposerreford) delete [] imposerreford;
03105 }
03106
03107 int ret_val = sym.guess(float(sigma));
03108 if (ret_val < 0) {
03109 Tcl_AppendResult(interp, "measure symmetry: ", measure_error(ret_val), NULL);
03110 return TCL_ERROR;
03111 }
03112
03113 int natoms = sel->selected;
03114 Symmetry *s = &sym;
03115
03116 if (idealsel) {
03117 Symmetry *isym = new Symmetry(idealsel, app->moleculeList, verbose);
03118 isym->set_overlaptol(float(sigma));
03119 isym->set_checkbonds(checkbonds);
03120 int j;
03121 float *plane = new float[3*sym.numplanes()];
03122 for (j=0; j<sym.numplanes(); j++) {
03123 vec_copy(&plane[3*j], sym.plane(j));
03124 }
03125 int *axisorder = new int[sym.numaxes()];
03126 float *axis = new float[3*sym.numaxes()];
03127 for (j=0; j<sym.numaxes(); j++) {
03128 axisorder[j] = sym.get_axisorder(j);
03129 vec_copy(&axis[3*j], sym.axis(j));
03130 }
03131 int *rrorder = new int[sym.numrotreflect()];
03132 float *rraxis = new float[3*sym.numrotreflect()];
03133 for (j=0; j<sym.numrotreflect(); j++) {
03134 rrorder[j] = sym.get_rotreflectorder(j);
03135 vec_copy(&rraxis[3*j], sym.rotreflect(j));
03136 }
03137
03138 int k=0, m=0;
03139 for (j=0; j<sel->num_atoms; j++) {
03140 if (idealsel->on[j]) {
03141 if (sel->on[j]) {
03142 vec_copy(isym->idealpos(k), sym.idealpos(m));
03143 m++;
03144 }
03145 k++;
03146 }
03147 }
03148 isym->impose(sym.has_inversion(),
03149 sym.numplanes(), plane,
03150 sym.numaxes(), axis, axisorder,
03151 sym.numrotreflect(), rraxis, rrorder);
03152
03153 ret_val = isym->guess(float(sigma));
03154 if (ret_val < 0) {
03155 Tcl_AppendResult(interp, "measure symmetry: ", measure_error(ret_val), NULL);
03156 return TCL_ERROR;
03157 }
03158
03159 natoms = idealsel->selected;
03160 s = isym;
03161 }
03162
03163 int pgorder;
03164 char pointgroup[6];
03165 s->get_pointgroup(pointgroup, &pgorder);
03166
03167 int i;
03168 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
03169 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("pointgroup", -1));
03170 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj(pointgroup, -1));
03171 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("order", -1));
03172 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewIntObj(pgorder));
03173 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("rmsd", -1));
03174 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(s->get_rmsd()));
03175 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("elements", -1));
03176 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj(s->get_element_summary(), -1));
03177 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("missing", -1));
03178 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj(s->get_missing_elements(), -1));
03179 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("additional", -1));
03180 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj(s->get_additional_elements(), -1));
03181
03182 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("com", -1));
03183 Tcl_Obj *invObj = Tcl_NewListObj(0, NULL);
03184 float *com = s->center_of_mass();
03185 Tcl_ListObjAppendElement(interp, invObj, Tcl_NewDoubleObj(com[0]));
03186 Tcl_ListObjAppendElement(interp, invObj, Tcl_NewDoubleObj(com[1]));
03187 Tcl_ListObjAppendElement(interp, invObj, Tcl_NewDoubleObj(com[2]));
03188 Tcl_ListObjAppendElement(interp, tcl_result, invObj);
03189
03190 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("inertia", -1));
03191 Tcl_Obj *inertListListObj = Tcl_NewListObj(0, NULL);
03192 float *inertia = s->get_inertia_axes();
03193 float *eigenval = s->get_inertia_eigenvals();
03194 int *unique = s->get_inertia_unique();
03195 for (i=0; i<3; i++) {
03196 Tcl_Obj *inertObj = Tcl_NewListObj(0, NULL);
03197 Tcl_ListObjAppendElement(interp, inertObj, Tcl_NewDoubleObj(inertia[3*i]));
03198 Tcl_ListObjAppendElement(interp, inertObj, Tcl_NewDoubleObj(inertia[3*i+1]));
03199 Tcl_ListObjAppendElement(interp, inertObj, Tcl_NewDoubleObj(inertia[3*i+2]));
03200 Tcl_Obj *inertListObj = Tcl_NewListObj(0, NULL);
03201 Tcl_ListObjAppendElement(interp, inertListObj, inertObj);
03202 Tcl_ListObjAppendElement(interp, inertListObj, Tcl_NewDoubleObj(eigenval[i]));
03203 Tcl_ListObjAppendElement(interp, inertListObj, Tcl_NewIntObj(unique[i]));
03204 Tcl_ListObjAppendElement(interp, inertListListObj, inertListObj);
03205 }
03206 Tcl_ListObjAppendElement(interp, tcl_result, inertListListObj);
03207
03208
03209 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("inversion", -1));
03210 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewIntObj(s->has_inversion()));
03211
03212
03213 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("axes", -1));
03214 Tcl_Obj *axesListListObj = Tcl_NewListObj(0, NULL);
03215 for (i=0; i<s->numaxes(); i++) {
03216 Tcl_Obj *axesObj = Tcl_NewListObj(0, NULL);
03217
03218 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(s->axis(i)[0]));
03219 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(s->axis(i)[1]));
03220 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(s->axis(i)[2]));
03221 Tcl_Obj *axesListObj = Tcl_NewListObj(0, NULL);
03222 Tcl_ListObjAppendElement(interp, axesListObj, axesObj);
03223 Tcl_ListObjAppendElement(interp, axesListObj, Tcl_NewIntObj(s->get_axisorder(i)));
03224 int axistype = s->get_axistype(i);
03225 if (axistype & PRINCIPAL_AXIS &&
03226 !(!s->is_spherical_top() && (axistype & PERPENDICULAR_AXIS))) {
03227 Tcl_ListObjAppendElement(interp, axesListObj, Tcl_NewStringObj("principal", -1));
03228 } else if (!s->is_spherical_top() && (axistype & PERPENDICULAR_AXIS)) {
03229 Tcl_ListObjAppendElement(interp, axesListObj, Tcl_NewStringObj("perpendicular", -1));
03230 } else {
03231 Tcl_ListObjAppendElement(interp, axesListObj, Tcl_NewListObj(0, NULL));
03232 }
03233 Tcl_ListObjAppendElement(interp, axesListListObj, axesListObj);
03234 }
03235 Tcl_ListObjAppendElement(interp, tcl_result, axesListListObj);
03236
03237
03238 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("rotreflect", -1));
03239 Tcl_Obj *rraxesListListObj = Tcl_NewListObj(0, NULL);
03240 for (i=0; i<s->numrotreflect(); i++) {
03241 Tcl_Obj *axesObj = Tcl_NewListObj(0, NULL);
03242
03243 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(s->rotreflect(i)[0]));
03244 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(s->rotreflect(i)[1]));
03245 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(s->rotreflect(i)[2]));
03246 Tcl_Obj *rraxesListObj = Tcl_NewListObj(0, NULL);
03247 Tcl_ListObjAppendElement(interp, rraxesListObj, axesObj);
03248 Tcl_ListObjAppendElement(interp, rraxesListObj, Tcl_NewIntObj(s->get_rotreflectorder(i)));
03249 Tcl_ListObjAppendElement(interp, rraxesListObj, Tcl_NewIntObj(s->get_rotrefltype(i)));
03250 Tcl_ListObjAppendElement(interp, rraxesListListObj, rraxesListObj);
03251 }
03252 Tcl_ListObjAppendElement(interp, tcl_result, rraxesListListObj);
03253
03254
03255 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("planes", -1));
03256 Tcl_Obj *planesListListObj = Tcl_NewListObj(0, NULL);
03257 for (i=0; i<s->numplanes(); i++) {
03258 Tcl_Obj *planesObj = Tcl_NewListObj(0, NULL);
03259
03260 Tcl_ListObjAppendElement(interp, planesObj, Tcl_NewDoubleObj(s->plane(i)[0]));
03261 Tcl_ListObjAppendElement(interp, planesObj, Tcl_NewDoubleObj(s->plane(i)[1]));
03262 Tcl_ListObjAppendElement(interp, planesObj, Tcl_NewDoubleObj(s->plane(i)[2]));
03263 Tcl_Obj *planesListObj = Tcl_NewListObj(0, NULL);
03264 Tcl_ListObjAppendElement(interp, planesListObj, planesObj);
03265 switch (s->get_planetype(i)) {
03266 case 1:
03267 Tcl_ListObjAppendElement(interp, planesListObj, Tcl_NewStringObj("vertical", -1));
03268 break;
03269 case 3:
03270 Tcl_ListObjAppendElement(interp, planesListObj, Tcl_NewStringObj("dihedral", -1));
03271 break;
03272 case 4:
03273 Tcl_ListObjAppendElement(interp, planesListObj, Tcl_NewStringObj("horizontal", -1));
03274 break;
03275 default:
03276 Tcl_ListObjAppendElement(interp, planesListObj, Tcl_NewListObj(0, NULL));
03277 }
03278 Tcl_ListObjAppendElement(interp, planesListListObj, planesListObj);
03279 }
03280 Tcl_ListObjAppendElement(interp, tcl_result, planesListListObj);
03281
03282
03283 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("ideal", -1));
03284 Tcl_Obj *idealcoorListObj = Tcl_NewListObj(0, NULL);
03285 for (i=0; i<natoms; i++) {
03286 Tcl_Obj *idealcoorObj = Tcl_NewListObj(0, NULL);
03287
03288 Tcl_ListObjAppendElement(interp, idealcoorObj, Tcl_NewDoubleObj(s->idealpos(i)[0]));
03289 Tcl_ListObjAppendElement(interp, idealcoorObj, Tcl_NewDoubleObj(s->idealpos(i)[1]));
03290 Tcl_ListObjAppendElement(interp, idealcoorObj, Tcl_NewDoubleObj(s->idealpos(i)[2]));
03291 Tcl_ListObjAppendElement(interp, idealcoorListObj, idealcoorObj);
03292 }
03293 Tcl_ListObjAppendElement(interp, tcl_result, idealcoorListObj);
03294
03295 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("unique", -1));
03296 Tcl_Obj *uniquecoorListObj = Tcl_NewListObj(0, NULL);
03297 for (i=0; i<natoms; i++) {
03298 if (!s->get_unique_atom(i)) continue;
03299 Tcl_ListObjAppendElement(interp, uniquecoorListObj, Tcl_NewIntObj(i));
03300 }
03301 Tcl_ListObjAppendElement(interp, tcl_result, uniquecoorListObj);
03302
03303 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("orient", -1));
03304 Matrix4 *orient = s->get_orientation();
03305 Tcl_Obj *matrixObj = Tcl_NewListObj(0, NULL);
03306 for (i=0; i<4; i++) {
03307 Tcl_Obj *rowObj = Tcl_NewListObj(0, NULL);
03308 Tcl_ListObjAppendElement(interp, rowObj, Tcl_NewDoubleObj(orient->mat[i+0]));
03309 Tcl_ListObjAppendElement(interp, rowObj, Tcl_NewDoubleObj(orient->mat[i+4]));
03310 Tcl_ListObjAppendElement(interp, rowObj, Tcl_NewDoubleObj(orient->mat[i+8]));
03311 Tcl_ListObjAppendElement(interp, rowObj, Tcl_NewDoubleObj(orient->mat[i+12]));
03312 Tcl_ListObjAppendElement(interp, matrixObj, rowObj);
03313 }
03314 Tcl_ListObjAppendElement(interp, tcl_result, matrixObj);
03315
03316 Tcl_SetObjResult(interp, tcl_result);
03317 if (idealsel) {
03318 delete s;
03319 }
03320 return TCL_OK;
03321
03322 }
03323
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333 static int vmd_measure_trans_overlap(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
03334 if (argc!=3 && argc!=5) {
03335 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> <matrix> [-sigma <value>]");
03336 return TCL_ERROR;
03337 }
03338 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
03339 if (!sel) {
03340 Tcl_AppendResult(interp, "measure transoverlap: no atom selection", NULL);
03341 return TCL_ERROR;
03342 }
03343 if (!app->molecule_valid_id(sel->molid())) {
03344 Tcl_AppendResult(interp, "measure transoverlap: ",
03345 measure_error(MEASURE_ERR_NOMOLECULE), NULL);
03346 return TCL_ERROR;
03347 }
03348
03349
03350 Matrix4 trans;
03351 if (tcl_get_matrix("measure transoverlap: ",interp,objv[2], trans.mat) != TCL_OK) {
03352 return TCL_ERROR;
03353 }
03354
03355 double sigma = 0.1;
03356 if (argc==5) {
03357 if (!strupncmp(Tcl_GetStringFromObj(objv[3],NULL), "-sigma", CMDLEN)) {
03358 if (Tcl_GetDoubleFromObj(interp, objv[4], &sigma) != TCL_OK) {
03359 Tcl_AppendResult(interp, " measure transoverlap: bad sigma value", NULL);
03360 return TCL_ERROR;
03361 }
03362 } else {
03363 Tcl_AppendResult(interp, " measure transoverlap: unrecognized option\n", NULL);
03364 Tcl_AppendResult(interp, " Usage: measure transoverlap <sel> <matrix> [-sigma <value>]", NULL);
03365 return TCL_ERROR;
03366 }
03367 }
03368
03369 int maxnatoms = 100;
03370 float overlap;
03371 int ret_val = measure_trans_overlap(sel, app->moleculeList, &trans,
03372 float(sigma), NOSKIP_IDENTICAL,
03373 maxnatoms, overlap);
03374 if (ret_val < 0) {
03375 Tcl_AppendResult(interp, "measure transoverlap: ", measure_error(ret_val), NULL);
03376 return TCL_ERROR;
03377 }
03378
03379 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
03380 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(overlap));
03381 Tcl_SetObjResult(interp, tcl_result);
03382
03383 return TCL_OK;
03384 }
03385
03386
03387
03388 int obj_measure(ClientData cd, Tcl_Interp *interp, int argc,
03389 Tcl_Obj * const objv[]) {
03390
03391 if (argc < 2) {
03392 Tcl_SetResult(interp,
03393 (char *) "usage: measure <command> [args...]\n"
03394 "\nMeasure Commands:\n"
03395 " avpos <sel> [first <first>] [last <last>] [step <step>] -- average position\n"
03396 " center <sel> [weight <weights>] -- geometrical (or weighted) center\n"
03397 " cluster <sel> [num <#clusters>] [distfunc <flag>] [cutoff <cutoff>]\n"
03398 " [first <first>] [last <last>] [step <step>] [selupdate <bool>]\n"
03399 " [weight <weights>]\n"
03400 " -- perform a cluster analysis (cluster similar timesteps)\n"
03401 " clustsize <sel> [cutoff <float>] [minsize <num>] [numshared <num>]\n"
03402 " [usepbc <bool>] [storesize <fieldname>] [storenum <fieldname>]\n"
03403 " -- perform a cluster size analysis (find clusters of atoms)\n"
03404 " contacts <cutoff> <sel1> [<sel2>] -- list contacts\n"
03405 " dipole <sel> [-elementary|-debye] [-geocenter|-masscenter|-origincenter]\n"
03406 " -- dipole moment\n"
03407 " fit <sel1> <sel2> [weight <weights>] [order <index list>]\n"
03408 " -- transformation matrix from selection 1 to 2\n"
03409 " gofr <sel1> <sel2> [delta <value>] [rmax <value>] [usepbc <bool>]\n"
03410 " [selupdate <bool>] [first <first>] [last <last>] [step <step>]\n"
03411 " -- atomic pair distribution function g(r)\n"
03412 " hbonds <cutoff> <angle> <sel1> [<sel2>]\n"
03413 " -- list donors, acceptors, hydrogens involved in hydrogen bonds\n"
03414 " inverse <matrix> -- inverse matrix\n"
03415 " inertia <sel> [-moments] [-eigenvals] -- COM and principle axes of inertia\n"
03416 " minmax <sel> [-withradii] -- bounding box\n"
03417 " rgyr <sel> [weight <weights>] -- radius of gyration\n"
03418 " rmsd <sel1> <sel2> [weight <weights>] -- RMS deviation\n"
03419 " rmsf <sel> [first <first>] [last <last>] [step <step>] -- RMS fluctuation\n"
03420 " sasa <srad> <sel> [-points <varname>] [-restrict <restrictedsel>]\n"
03421 " [-samples <numsamples>] -- solvent-accessible surface area\n"
03422 " sumweights <sel> weight <weights> -- sum of selected weights\n"
03423 " bond {{<atomid1> [<molid1>]} {<atomid2> [<molid2>]}}\n"
03424 " [molid <default mol>] [frame <frame|all|last> | first <first> last <last>]\n"
03425 " -- bond length between atoms 1 and 2\n"
03426 " angle {{<atomid1> [<molid1>]} {<atomid2> [<molid2>]} {<atomid3> [<molid3>]}}\n"
03427 " [molid <default mol>] [frame <frame|all|last> | first <first> last <last>]\n"
03428 " -- angle between atoms 1-3\n"
03429 " dihed {{<atomid1> [<molid1>]} ... {<atomid4> [<molid4>]}}\n"
03430 " [molid <default mol>] [frame <frame|all|last> | first <first> last <last>]\n"
03431 " -- dihedral angle between atoms 1-4\n"
03432 " imprp {{<atomid1> [<molid1>]} ... {<atomid4> [<molid4>]}}\n"
03433 " [molid <default mol>] [frame <frame|all|last> | first <first> last <last>]\n"
03434 " -- improper angle between atoms 1-4\n"
03435
03436 " energy bond|angle|dihed|impr|vdw|elec -- compute energy\n"
03437 " surface <sel> <gridsize> <radius> <thickness> -- surface of selection\n"
03438 " pbc2onc <center> [molid <default>] [frame <frame|last>]\n"
03439 " -- transformation matrix to wrap a nonorthogonal PBC unit cell\n"
03440 " into an orthonormal cell\n"
03441 " pbcneighbors <center> <cutoff> [sel <sel>] [align <matrix>] [molid <default>]\n"
03442 " [frame <frame|last>] [boundingbox <PBC|{<mincoord> <maxcoord>}>]\n"
03443 " -- all image atoms that are within cutoff Angstrom of the pbc unit cell\n"
03444 " symmetry <sel> [element [<vector>]] [-tol <value>] [-nobonds] [-verbose <level>]\n"
03445 " transoverlap <sel> <matrix> [-sigma <value>]\n"
03446 " -- overlap of a structure with a transformed copy of itself\n",
03447 TCL_STATIC);
03448 return TCL_ERROR;
03449 }
03450 VMDApp *app = (VMDApp *)cd;
03451 char *argv1 = Tcl_GetStringFromObj(objv[1],NULL);
03452 if (!strupncmp(argv1, "avpos", CMDLEN))
03453 return vmd_measure_avpos(app, argc-1, objv+1, interp);
03454 else if (!strupncmp(argv1, "center", CMDLEN))
03455 return vmd_measure_center(app, argc-1, objv+1, interp);
03456 else if (!strupncmp(argv1, "cluster", CMDLEN))
03457 return vmd_measure_cluster(app, argc-1, objv+1, interp);
03458 else if (!strupncmp(argv1, "clustsize", CMDLEN))
03459 return vmd_measure_clustsize(app, argc-1, objv+1, interp);
03460 else if (!strupncmp(argv1, "contacts", CMDLEN))
03461 return vmd_measure_contacts(app, argc-1, objv+1, interp);
03462 else if (!strupncmp(argv1, "dipole", CMDLEN))
03463 return vmd_measure_dipole(app, argc-1, objv+1, interp);
03464 else if (!strupncmp(argv1, "fit", CMDLEN))
03465 return vmd_measure_fit(app, argc-1, objv+1, interp);
03466 else if (!strupncmp(argv1, "minmax", CMDLEN))
03467 return vmd_measure_minmax(app, argc-1, objv+1, interp);
03468 else if (!strupncmp(argv1, "gofr", CMDLEN))
03469 return vmd_measure_gofr(app, argc-1, objv+1, interp);
03470 else if (!strupncmp(argv1, "rdf", CMDLEN))
03471 return vmd_measure_rdf(app, argc-1, objv+1, interp);
03472 else if (!strupncmp(argv1, "hbonds", CMDLEN))
03473 return vmd_measure_hbonds(app, argc-1, objv+1, interp);
03474 else if (!strupncmp(argv1, "inverse", CMDLEN))
03475 return vmd_measure_inverse(argc-1, objv+1, interp);
03476 else if (!strupncmp(argv1, "inertia", CMDLEN))
03477 return vmd_measure_inertia(app, argc-1, objv+1, interp);
03478 else if (!strupncmp(argv1, "rgyr", CMDLEN))
03479 return vmd_measure_rgyr(app, argc-1, objv+1, interp);
03480 else if (!strupncmp(argv1, "rmsd", CMDLEN))
03481 return vmd_measure_rmsd(app, argc-1, objv+1, interp);
03482 else if (!strupncmp(argv1, "rmsf", CMDLEN))
03483 return vmd_measure_rmsf(app, argc-1, objv+1, interp);
03484 else if (!strupncmp(argv1, "sasa", CMDLEN))
03485 return vmd_measure_sasa(app, argc-1, objv+1, interp);
03486 else if (!strupncmp(argv1, "sumweights", CMDLEN))
03487 return vmd_measure_sumweights(app, argc-1, objv+1, interp);
03488 else if (!strupncmp(argv1, "imprp", CMDLEN))
03489 return vmd_measure_dihed(app, argc-1, objv+1, interp);
03490 else if (!strupncmp(argv1, "dihed", CMDLEN))
03491 return vmd_measure_dihed(app, argc-1, objv+1, interp);
03492 else if (!strupncmp(argv1, "angle", CMDLEN))
03493 return vmd_measure_angle(app, argc-1, objv+1, interp);
03494 else if (!strupncmp(argv1, "bond", CMDLEN))
03495 return vmd_measure_bond(app, argc-1, objv+1, interp);
03496 else if (!strupncmp(argv1, "energy", CMDLEN))
03497 return vmd_measure_energy(app, argc-1, objv+1, interp);
03498 else if (!strupncmp(argv1, "pbc2onc", CMDLEN))
03499 return vmd_measure_pbc2onc_transform(app, argc-1, objv+1, interp);
03500 else if (!strupncmp(argv1, "pbcneighbors", CMDLEN))
03501 return vmd_measure_pbc_neighbors(app, argc-1, objv+1, interp);
03502 else if (!strupncmp(argv1, "surface", CMDLEN))
03503 return vmd_measure_surface(app, argc-1, objv+1, interp);
03504 else if (!strupncmp(argv1, "transoverlap", CMDLEN))
03505 return vmd_measure_trans_overlap(app, argc-1, objv+1, interp);
03506 else if (!strupncmp(argv1, "symmetry", CMDLEN))
03507 return vmd_measure_symmetry(app, argc-1, objv+1, interp);
03508
03509 Tcl_SetResult(interp, (char *) "Type 'measure' for summary of usage\n", TCL_VOLATILE);
03510 return TCL_OK;
03511 }
03512
03513
03514