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 <math.h>
00027 #include "TclCommands.h"
00028 #include "AtomSel.h"
00029 #include "Matrix4.h"
00030 #include "SymbolTable.h"
00031 #include "VMDApp.h"
00032 #include "MoleculeList.h"
00033 #include "utilities.h"
00034 #include "config.h"
00035 #include "Measure.h"
00036 #include "MeasureSymmetry.h"
00037 #include "SpatialSearch.h"
00038 #include "Atom.h"
00039 #include "Molecule.h"
00040
00041
00042 #include "QuickSurf.h"
00043 #include "MDFF.h"
00044 #include "CUDAMDFF.h"
00045 #include "MeasureVolInterior.h"
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 char *weight_string = NULL;
00060
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 MEASURE_NOERR;
00071 }
00072
00073
00074 SymbolTable *atomSelParser = app->atomSelParser;
00075
00076
00077
00078 atomsel_ctxt context(atomSelParser,
00079 app->moleculeList->mol_from_id(sel->molid()),
00080 sel->which_frame, NULL);
00081
00082 int fctn = atomSelParser->find_attribute(weight_string);
00083 if (fctn >= 0) {
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
00091 double *tmp_data = new double[sel->num_atoms];
00092 atomSelParser->fctns.data(fctn)->keyword_double(&context,
00093 sel->num_atoms, tmp_data, sel->on);
00094
00095 for (int i=sel->firstsel, j=0; i<=sel->lastsel; i++) {
00096 if (sel->on[i])
00097 data[j++] = (float)tmp_data[i];
00098 }
00099
00100 delete [] tmp_data;
00101 return MEASURE_NOERR;
00102 }
00103
00104
00105 int list_num;
00106 Tcl_Obj **list_data;
00107 if (Tcl_ListObjGetElements(interp, weight_obj, &list_num, &list_data)
00108 != TCL_OK) {
00109 return MEASURE_ERR_BADWEIGHTPARM;
00110 }
00111 if (list_num != sel->selected && list_num != sel->num_atoms)
00112 return MEASURE_ERR_BADWEIGHTNUM;
00113
00114 for (int i=0, j=0; i<list_num; i++) {
00115 double tmp_data;
00116
00117 if (Tcl_GetDoubleFromObj(interp, list_data[i], &tmp_data) != TCL_OK)
00118 return MEASURE_ERR_NONNUMBERPARM;
00119
00120 if (list_num == sel->selected) {
00121 data[i] = (float)tmp_data;
00122 } else {
00123 if (sel->on[i]) {
00124 data[j++] = (float)tmp_data;
00125 }
00126 }
00127 }
00128
00129 return MEASURE_NOERR;
00130 }
00131
00132
00133 int atomsel_default_weights(AtomSel *sel, float *weights) {
00134 if (sel->firstsel > 0)
00135 memset(&weights[0], 0, sel->firstsel * sizeof(float));
00136
00137 for (int i=sel->firstsel; i<=sel->lastsel; i++) {
00138
00139 weights[i] = sel->on[i] ? 1.0f : 0.0f;
00140 }
00141
00142 if (sel->lastsel < (sel->num_atoms - 1))
00143 memset(&weights[sel->lastsel+1], 0, ((sel->num_atoms - 1) - sel->lastsel) * sizeof(float));
00144
00145 return 0;
00146 }
00147
00148
00149 int get_weights_from_tcl_list(Tcl_Interp *interp, VMDApp *app, AtomSel *sel,
00150 Tcl_Obj *weights_obj, float *weights) {
00151 int list_num = 0;
00152 Tcl_Obj **list_elems = NULL;
00153 if (Tcl_ListObjGetElements(interp, weights_obj, &list_num, &list_elems)
00154 != TCL_OK) {
00155 return MEASURE_ERR_BADWEIGHTPARM;
00156 }
00157 if (list_num != sel->num_atoms) {
00158 return MEASURE_ERR_BADWEIGHTNUM;
00159 }
00160 for (int i = 0; i < sel->num_atoms; i++) {
00161 double tmp_data = 0.0;
00162 if (Tcl_GetDoubleFromObj(interp, list_elems[i], &tmp_data) != TCL_OK) {
00163 return TCL_ERROR;
00164 }
00165 weights[i] = static_cast<float>(tmp_data);
00166 }
00167 return 0;
00168 }
00169
00170
00171
00172
00173
00174 int get_attribute_index(VMDApp *app, char const *string) {
00175 SymbolTable *atomSelParser = app->atomSelParser;
00176 return atomSelParser->find_attribute(string);
00177 }
00178
00179
00180 int get_weights_from_attribute(VMDApp *app, AtomSel *sel,
00181 char const *weights_string, float *weights) {
00182 SymbolTable *atomSelParser = app->atomSelParser;
00183 int fctn = atomSelParser->find_attribute(weights_string);
00184
00185
00186 if (atomSelParser->fctns.data(fctn)->returns_a !=
00187 SymbolTableElement::IS_FLOAT) {
00188 return MEASURE_ERR_BADWEIGHTPARM;
00189 }
00190 atomsel_ctxt context(atomSelParser,
00191 app->moleculeList->mol_from_id(sel->molid()),
00192 sel->which_frame, NULL);
00193 double *tmp_data = new double[sel->num_atoms];
00194 atomSelParser->fctns.data(fctn)->keyword_double(&context, sel->num_atoms,
00195 tmp_data, sel->on);
00196
00197 if (sel->firstsel > 0)
00198 memset(&weights[0], 0, sel->firstsel * sizeof(float));
00199
00200 for (int i=sel->firstsel; i<=sel->lastsel; i++) {
00201 weights[i] = sel->on[i] ? static_cast<float>(tmp_data[i]) : 0.0f;
00202 }
00203
00204 if (sel->lastsel < (sel->num_atoms - 1))
00205 memset(&weights[sel->lastsel+1], 0, ((sel->num_atoms - 1) - sel->lastsel) * sizeof(float));
00206
00207 delete [] tmp_data;
00208 return 0;
00209 }
00210
00211
00212
00213 int tcl_get_orders(Tcl_Interp *interp, int selnum,
00214 Tcl_Obj *order_obj, int *data) {
00215 int list_num;
00216 Tcl_Obj **list_data;
00217
00218 if (Tcl_ListObjGetElements(interp, order_obj, &list_num, &list_data)
00219 != TCL_OK) {
00220 return MEASURE_ERR_NOSEL;
00221 }
00222
00223
00224 if (list_num != selnum) return MEASURE_ERR_NOSEL;
00225
00226 for (int i=0; i<list_num; i++) {
00227 if (Tcl_GetIntFromObj(interp, list_data[i], &data[i]) != TCL_OK)
00228 return MEASURE_ERR_NONNUMBERPARM;
00229
00230
00231 if (data[i] < 0 || data[i] >= selnum)
00232 return MEASURE_ERR_BADORDERINDEX;
00233 }
00234
00235 return MEASURE_NOERR;
00236 }
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258 static int vmd_measure_center(VMDApp *app, int argc, Tcl_Obj *const objv[], Tcl_Interp *interp) {
00259 if (argc != 2 && argc != 4 ) {
00260 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<sel> [weight <weights>]");
00261 return TCL_ERROR;
00262 }
00263 if (argc == 4 && strcmp(Tcl_GetStringFromObj(objv[2],NULL), "weight")) {
00264 Tcl_SetResult(interp, (char *) "measure center: parameter can only be 'weight'", TCL_STATIC);
00265 return TCL_ERROR;
00266 }
00267
00268
00269 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
00270 if (!sel) {
00271 Tcl_SetResult(interp, (char *) "measure center: no atom selection", TCL_STATIC);
00272 return TCL_ERROR;
00273 }
00274
00275
00276 float *weight = new float[sel->selected];
00277 int ret_val=0;
00278 if (argc == 2) {
00279 ret_val = tcl_get_weights(interp, app, sel, NULL, weight);
00280 } else {
00281 ret_val = tcl_get_weights(interp, app, sel, objv[3], weight);
00282 }
00283 if (ret_val < 0) {
00284 Tcl_AppendResult(interp, "measure center: ", measure_error(ret_val), NULL);
00285 delete [] weight;
00286 return TCL_ERROR;
00287 }
00288
00289
00290 float com[3];
00291 const float *framepos = sel->coordinates(app->moleculeList);
00292 ret_val = measure_center(sel, framepos, weight, com);
00293 delete [] weight;
00294 if (ret_val < 0) {
00295 Tcl_AppendResult(interp, "measure center: ", measure_error(ret_val), NULL);
00296 return TCL_ERROR;
00297 }
00298
00299 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00300 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(com[0]));
00301 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(com[1]));
00302 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(com[2]));
00303 Tcl_SetObjResult(interp, tcl_result);
00304
00305 return TCL_OK;
00306 }
00307
00308
00309 static int vmd_measure_centerperresidue(VMDApp *app, int argc, Tcl_Obj *const objv[], Tcl_Interp *interp) {
00310 int ret_val = 0;
00311
00312
00313 if (argc != 2 && argc != 4 ) {
00314 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<sel> [weight <weights>]");
00315 return TCL_ERROR;
00316 }
00317
00318
00319 if (argc == 4 && strcmp(Tcl_GetStringFromObj(objv[2], NULL), "weight")) {
00320 Tcl_SetResult(interp, (char *) "measure centerperresidue: parameter can only be 'weight'", TCL_STATIC);
00321 return TCL_ERROR;
00322 }
00323
00324
00325 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1], NULL));
00326 if (!sel) {
00327 Tcl_SetResult(interp, (char *) "measure centerperresidue: no atom selection", TCL_STATIC);
00328 return TCL_ERROR;
00329 }
00330
00331
00332 float *weight = new float[sel->selected];
00333 if (argc == 2) {
00334
00335 ret_val = tcl_get_weights(interp, app, sel, NULL, weight);
00336 } else {
00337
00338 ret_val = tcl_get_weights(interp, app, sel, objv[3], weight);
00339 }
00340 if (ret_val < 0) {
00341 Tcl_AppendResult(interp, "measure centerperresidue: ",
00342 measure_error(ret_val), NULL);
00343 delete [] weight;
00344 return TCL_ERROR;
00345 }
00346
00347
00348 float *com = new float[3*sel->selected];
00349 const float *framepos = sel->coordinates(app->moleculeList);
00350 ret_val = measure_center_perresidue(app->moleculeList, sel,
00351 framepos, weight, com);
00352 delete [] weight;
00353 if (ret_val < 0) {
00354 Tcl_AppendResult(interp, "measure centerperresidue: ",
00355 measure_error(ret_val), NULL);
00356 return TCL_ERROR;
00357 }
00358
00359
00360 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00361 for (int i=0; i<ret_val; i++) {
00362 Tcl_Obj *m = Tcl_NewListObj(0, NULL);
00363 for (int j=0; j<3; j++) {
00364 Tcl_ListObjAppendElement(interp, m, Tcl_NewDoubleObj(com[3*i+j]));
00365 }
00366 Tcl_ListObjAppendElement(interp, tcl_result, m);
00367 }
00368 Tcl_SetObjResult(interp, tcl_result);
00369 delete [] com;
00370
00371 return TCL_OK;
00372 }
00373
00374
00375
00376 static int vmd_measure_sumweights(VMDApp *app, int argc, Tcl_Obj *const objv[], Tcl_Interp *interp) {
00377 if (argc != 4) {
00378 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<sel> weight <weights>");
00379 return TCL_ERROR;
00380 }
00381 if (strcmp(Tcl_GetStringFromObj(objv[2],NULL), "weight")) {
00382 Tcl_SetResult(interp, (char *) "measure sumweights: parameter can only be 'weight'", TCL_STATIC);
00383 return TCL_ERROR;
00384 }
00385
00386
00387 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL)
00388 );
00389 if (!sel) {
00390 Tcl_SetResult(interp, (char *) "measure sumweights: no atom selection", TCL_STATIC);
00391 return TCL_ERROR;
00392 }
00393
00394
00395 float *weight = new float[sel->selected];
00396 int ret_val = 0;
00397 ret_val = tcl_get_weights(interp, app, sel, objv[3], weight);
00398 if (ret_val < 0) {
00399 Tcl_AppendResult(interp, "measure center: ", measure_error(ret_val), NULL);
00400 delete [] weight;
00401 return TCL_ERROR;
00402 }
00403
00404
00405 float weightsum=0;
00406 ret_val = measure_sumweights(sel, sel->selected, weight, &weightsum);
00407 delete [] weight;
00408 if (ret_val < 0) {
00409 Tcl_AppendResult(interp, "measure center: ", measure_error(ret_val), NULL);
00410 return TCL_ERROR;
00411 }
00412
00413 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00414 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(weightsum));
00415 Tcl_SetObjResult(interp, tcl_result);
00416
00417 return TCL_OK;
00418 }
00419
00420
00421
00422
00423
00424 static int vmd_measure_avpos(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00425 int first = 0;
00426 int last = -1;
00427 int step = 1;
00428
00429 if (argc < 2 || argc > 8) {
00430 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> [first <first>] [last <last>] [step <step>]");
00431 return TCL_ERROR;
00432 }
00433 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL)
00434 );
00435 if (!sel) {
00436 Tcl_AppendResult(interp, "measure avpos: no atom selection", NULL);
00437 return TCL_ERROR;
00438 }
00439
00440 int i;
00441 for (i=2; i<argc; i+=2) {
00442 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00443 if (!strupncmp(argvcur, "first", CMDLEN)) {
00444 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00445 Tcl_AppendResult(interp, "measure avpos: bad first frame value", NULL);
00446 return TCL_ERROR;
00447 }
00448 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00449 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00450 Tcl_AppendResult(interp, "measure avpos: bad last frame value", NULL);
00451 return TCL_ERROR;
00452 }
00453 } else if (!strupncmp(argvcur, "step", CMDLEN)) {
00454 if (Tcl_GetIntFromObj(interp, objv[i+1], &step) != TCL_OK) {
00455 Tcl_AppendResult(interp, "measure avpos: bad frame step value", NULL);
00456 return TCL_ERROR;
00457 }
00458 } else {
00459 Tcl_AppendResult(interp, "measure rmsdmat_qcp: invalid syntax, no such keyword: ", argvcur, NULL);
00460 return TCL_ERROR;
00461 }
00462 }
00463
00464 float *avpos = new float[3L*sel->selected];
00465 int ret_val = measure_avpos(sel, app->moleculeList, first, last, step, avpos);
00466 if (ret_val < 0) {
00467 Tcl_AppendResult(interp, "measure avpos: ", measure_error(ret_val), NULL);
00468 delete [] avpos;
00469 return TCL_ERROR;
00470 }
00471
00472 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00473 for (i=0; i<sel->selected; i++) {
00474 Tcl_Obj *atom = Tcl_NewListObj(0, NULL);
00475 Tcl_ListObjAppendElement(interp, atom, Tcl_NewDoubleObj(avpos[i*3L ]));
00476 Tcl_ListObjAppendElement(interp, atom, Tcl_NewDoubleObj(avpos[i*3L + 1]));
00477 Tcl_ListObjAppendElement(interp, atom, Tcl_NewDoubleObj(avpos[i*3L + 2]));
00478 Tcl_ListObjAppendElement(interp, tcl_result, atom);
00479 }
00480
00481 Tcl_SetObjResult(interp, tcl_result);
00482 delete [] avpos;
00483
00484 return TCL_OK;
00485 }
00486
00487
00488
00489
00490 static int vmd_measure_dipole(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00491 const char *opt;
00492 int unitsdebye=0;
00493 int usecenter=1;
00494
00495 if ((argc < 2) || (argc > 4)) {
00496 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> [-elementary|-debye] [-geocenter|-masscenter|-origincenter]");
00497 return TCL_ERROR;
00498 }
00499 AtomSel *sel;
00500 sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1], NULL));
00501 if (!sel) {
00502 Tcl_AppendResult(interp, "measure dipole: no atom selection", NULL);
00503 return TCL_ERROR;
00504 }
00505
00506 int i;
00507 for (i=0; i < (argc-2); ++i) {
00508 opt = Tcl_GetStringFromObj(objv[2+i], NULL);
00509 if (!strcmp(opt, "-debye"))
00510 unitsdebye=1;
00511 if (!strcmp(opt, "-elementary"))
00512 unitsdebye=0;
00513
00514 if (!strcmp(opt, "-geocenter"))
00515 usecenter=1;
00516 if (!strcmp(opt, "-masscenter"))
00517 usecenter=-1;
00518 if (!strcmp(opt, "-origincenter"))
00519 usecenter=0;
00520 }
00521
00522 float dipole[3];
00523 int ret_val = measure_dipole(sel, app->moleculeList, dipole, unitsdebye, usecenter);
00524 if (ret_val < 0) {
00525 Tcl_AppendResult(interp, "measure dipole: ", measure_error(ret_val), NULL);
00526 return TCL_ERROR;
00527 }
00528
00529 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00530 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(dipole[0]));
00531 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(dipole[1]));
00532 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(dipole[2]));
00533 Tcl_SetObjResult(interp, tcl_result);
00534
00535 return TCL_OK;
00536 }
00537
00538
00539
00540
00541
00542
00543 static int vmd_measure_dihed(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00544 int first=-1, last=-1, frame=-1;
00545 if (argc < 2) {
00546 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>]");
00547 return TCL_ERROR;
00548 }
00549
00550 int molid[4], atmid[4], defmolid = -1;
00551 bool allframes = false;
00552
00553
00554 char *geomname = Tcl_GetStringFromObj(objv[0],NULL);
00555
00556
00557 int numatms;
00558 Tcl_Obj **data;
00559 if (Tcl_ListObjGetElements(interp, objv[1], &numatms, &data) != TCL_OK) {
00560 Tcl_AppendResult(interp, " measure ", geomname, ": bad syntax", NULL);
00561 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);
00562 return TCL_ERROR;
00563 }
00564
00565 if (numatms != 4) {
00566 Tcl_AppendResult(interp, " measure dihed: must specify exactly four atoms in a list", NULL);
00567 return TCL_ERROR;
00568 }
00569
00570 if (argc > 3) {
00571 int i;
00572 for (i=2; i<argc; i+=2) {
00573 char *argvcur = Tcl_GetStringFromObj(objv[i], NULL);
00574 if (!strupncmp(argvcur, "molid", CMDLEN)) {
00575 if (Tcl_GetIntFromObj(interp, objv[i+1], &defmolid) != TCL_OK) {
00576 Tcl_AppendResult(interp, " measure ", geomname, ": bad molid", NULL);
00577 return TCL_ERROR;
00578 }
00579 } else if (!strupncmp(argvcur, "first", CMDLEN)) {
00580 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00581 Tcl_AppendResult(interp, " measure ", geomname, ": bad first frame value", NULL);
00582 return TCL_ERROR;
00583 }
00584 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00585 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00586 Tcl_AppendResult(interp, " measure ", geomname, ": bad last frame value", NULL);
00587 return TCL_ERROR;
00588 }
00589 } else if (!strupncmp(argvcur, "frame", CMDLEN)) {
00590 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "all")) {
00591 allframes = true;
00592 } else if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "last")) {
00593 frame=-2;
00594 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &frame) != TCL_OK) {
00595 Tcl_AppendResult(interp, " measure ", geomname, ": bad frame value", NULL);
00596 return TCL_ERROR;
00597 }
00598 } else {
00599 Tcl_AppendResult(interp, "measure ", geomname, ": invalid syntax, no such keyword: ", argvcur, NULL);
00600 return TCL_ERROR;
00601 }
00602 }
00603 }
00604
00605 if ((allframes || frame>=0) && (first>=0 || last>=0)) {
00606 Tcl_AppendResult(interp, "measure ", geomname, ": Ambiguous syntax: You cannot specify a frame AND a frame range (using first or last).", NULL);
00607 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);
00608 return TCL_ERROR;
00609 }
00610
00611 if (allframes) first=0;
00612
00613
00614 if (defmolid<0) defmolid = app->molecule_top();
00615
00616
00617 int i,numelem;
00618 Tcl_Obj **atmmol;
00619 for (i=0; i<numatms; i++) {
00620 if (Tcl_ListObjGetElements(interp, data[i], &numelem, &atmmol) != TCL_OK) {
00621 return TCL_ERROR;
00622 }
00623
00624 if (!numelem) {
00625 Tcl_AppendResult(interp, " measure ", geomname, ": empty atom index", NULL);
00626 return TCL_ERROR;
00627 }
00628
00629 if (Tcl_GetIntFromObj(interp, atmmol[0], atmid+i) != TCL_OK) {
00630 Tcl_AppendResult(interp, " measure ", geomname, ": bad atom index", NULL);
00631 return TCL_ERROR;
00632 }
00633
00634 if (numelem==2) {
00635 if (Tcl_GetIntFromObj(interp, atmmol[1], molid+i) != TCL_OK) {
00636 Tcl_AppendResult(interp, " measure ", geomname, ": bad molid", NULL);
00637 return TCL_ERROR;
00638 }
00639 } else molid[i] = defmolid;
00640 }
00641
00642
00643 ResizeArray<float> gValues(1024);
00644 int ret_val;
00645 ret_val = measure_geom(app->moleculeList, molid, atmid, &gValues,
00646 frame, first, last, defmolid, MEASURE_DIHED);
00647 if (ret_val < 0) {
00648 Tcl_AppendResult(interp, measure_error(ret_val), NULL);
00649 return TCL_ERROR;
00650 }
00651
00652 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00653 int numvalues = gValues.num();
00654 for (int count = 0; count < numvalues; count++) {
00655 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(gValues[count]));
00656 }
00657 Tcl_SetObjResult(interp, tcl_result);
00658
00659 return TCL_OK;
00660 }
00661
00662
00663
00664
00665
00666 static int vmd_measure_angle(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00667 int first=-1, last=-1, frame=-1;
00668
00669 if(argc<2) {
00670 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "{{<atomid1> [<molid1>]} {<atomid2> [<molid2>]} {<atomid3> [<molid3>]}} [molid <default molid>] [frame <frame|all|last> | first <first> last <last>]");
00671 return TCL_ERROR;
00672 }
00673
00674 int molid[3], atmid[3], defmolid = -1;
00675 bool allframes = false;
00676
00677
00678 int numatms;
00679 Tcl_Obj **data;
00680 if (Tcl_ListObjGetElements(interp, objv[1], &numatms, &data) != TCL_OK) {
00681 Tcl_AppendResult(interp, " measure bond: bad syntax", NULL);
00682 Tcl_AppendResult(interp, " Usage: measure angle {{<atomid1> [<molid1>]} {<atomid2> [<molid2>]} {<atomid3> [<molid3>]}} [molid <default molid>] [frame <frame|all|last> | first <first> last <last>]", NULL);
00683 return TCL_ERROR;
00684 }
00685
00686 if (numatms != 3) {
00687 Tcl_AppendResult(interp, " measure angle: must specify exactly three atoms in a list", NULL);
00688 return TCL_ERROR;
00689 }
00690
00691 if (argc > 3) {
00692 for (int i=2; i<argc; i+=2) {
00693 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00694 if (!strupncmp(argvcur, "molid", CMDLEN)) {
00695 if (Tcl_GetIntFromObj(interp, objv[i+1], &defmolid) != TCL_OK) {
00696 Tcl_AppendResult(interp, " measure angle: bad molid", NULL);
00697 return TCL_ERROR;
00698 }
00699 } else if (!strupncmp(argvcur, "first", CMDLEN)) {
00700 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00701 Tcl_AppendResult(interp, " measure angle: bad first frame value", NULL);
00702 return TCL_ERROR;
00703 }
00704 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00705 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00706 Tcl_AppendResult(interp, " measure angle: bad last frame value", NULL);
00707 return TCL_ERROR;
00708 }
00709 } else if (!strupncmp(argvcur, "frame", CMDLEN)) {
00710 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "all")) {
00711 allframes = true;
00712 } else if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "last")) {
00713 frame=-2;
00714 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &frame) != TCL_OK) {
00715 Tcl_AppendResult(interp, " measure angle: bad frame value", NULL);
00716 return TCL_ERROR;
00717 }
00718 } else {
00719 Tcl_AppendResult(interp, " measure angle: invalid syntax, no such keyword: ", argvcur, NULL);
00720 return TCL_ERROR;
00721 }
00722 }
00723 }
00724
00725 if ((allframes || frame>=0) && (first>=0 || last>=0)) {
00726 Tcl_AppendResult(interp, "measure angle: Ambiguous syntax: You cannot specify a frame AND a frame range (using first or last).", NULL);
00727 Tcl_AppendResult(interp, "\nUsage:\nmeasure angle {<atomid1> [<molid1>]} {<atomid2> [<molid2>]} {<atomid3> [<molid3>]}} [molid <default molid>] [frame <frame|all|last> | first <first> last <last>]", NULL);
00728 return TCL_ERROR;
00729 }
00730
00731 if (allframes) first=0;
00732
00733
00734 if (defmolid<0) defmolid = app->molecule_top();
00735
00736
00737 int i,numelem;
00738 Tcl_Obj **atmmol;
00739 for (i=0; i<numatms; i++) {
00740 if (Tcl_ListObjGetElements(interp, data[i], &numelem, &atmmol) != TCL_OK) {
00741 return TCL_ERROR;
00742 }
00743
00744 if (!numelem) {
00745 Tcl_AppendResult(interp, " measure angle: empty atom index", NULL);
00746 return TCL_ERROR;
00747 }
00748
00749 if (Tcl_GetIntFromObj(interp, atmmol[0], atmid+i) != TCL_OK) {
00750 Tcl_AppendResult(interp, " measure angle: bad atom index", NULL);
00751 return TCL_ERROR;
00752 }
00753
00754 if (numelem==2) {
00755 if (Tcl_GetIntFromObj(interp, atmmol[1], molid+i) != TCL_OK) {
00756 Tcl_AppendResult(interp, " measure angle: bad molid", NULL);
00757 return TCL_ERROR;
00758 }
00759 } else molid[i] = defmolid;
00760 }
00761
00762
00763 ResizeArray<float> gValues(1024);
00764 int ret_val;
00765 ret_val = measure_geom(app->moleculeList, molid, atmid, &gValues,
00766 frame, first, last, defmolid, MEASURE_ANGLE);
00767 if (ret_val<0) {
00768 printf("ERROR\n %s\n", measure_error(ret_val));
00769 Tcl_AppendResult(interp, measure_error(ret_val), NULL);
00770 return TCL_ERROR;
00771 }
00772
00773 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00774 int numvalues = gValues.num();
00775 for (int count = 0; count < numvalues; count++) {
00776 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(gValues[count]));
00777 }
00778 Tcl_SetObjResult(interp, tcl_result);
00779
00780 return TCL_OK;
00781 }
00782
00783
00784
00785
00786 static int vmd_measure_bond(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00787 int first=-1, last=-1, frame=-1;
00788
00789 if (argc<2) {
00790 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "{{<atomid1> [<molid1>]} {<atomid2> [<molid2>]}} [molid <default molid>] [frame <frame|all|last> | first <first> last <last>]]");
00791 return TCL_ERROR;
00792 }
00793
00794 int molid[2], atmid[2], defmolid = -1;
00795 bool allframes = false;
00796
00797
00798 int numatms=0;
00799 Tcl_Obj **data;
00800 if (Tcl_ListObjGetElements(interp, objv[1], &numatms, &data) != TCL_OK) {
00801 Tcl_AppendResult(interp, " measure bond: bad syntax", NULL);
00802 Tcl_AppendResult(interp, " Usage: measure bond {{<atomid1> [<molid1>]} {<atomid2> [<molid2>]}} [molid <default>] [frame <frame|all|last> | first <first> last <last>]]", NULL);
00803 return TCL_ERROR;
00804 }
00805
00806 if (numatms != 2) {
00807 Tcl_AppendResult(interp, " measure bond: must specify exactly two atoms in a list", NULL);
00808 return TCL_ERROR;
00809 }
00810
00811 if (argc > 3) {
00812 for (int i=2; i<argc; i+=2) {
00813 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00814 if (!strupncmp(argvcur, "molid", CMDLEN)) {
00815 if (Tcl_GetIntFromObj(interp, objv[i+1], &defmolid) != TCL_OK) {
00816 Tcl_AppendResult(interp, " measure bond: bad molid", NULL);
00817 return TCL_ERROR;
00818 }
00819 } else if (!strupncmp(argvcur, "first", CMDLEN)) {
00820 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00821 Tcl_AppendResult(interp, " measure bond: bad first frame value", NULL);
00822 return TCL_ERROR;
00823 }
00824 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00825 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00826 Tcl_AppendResult(interp, " measure bond: bad last frame value", NULL);
00827 return TCL_ERROR;
00828 }
00829 } else if (!strupncmp(argvcur, "frame", CMDLEN)) {
00830 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "all")) {
00831 allframes = true;
00832 } else if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "last")) {
00833 frame=-2;
00834 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &frame) != TCL_OK) {
00835 Tcl_AppendResult(interp, " measure bond: bad frame value", NULL);
00836 return TCL_ERROR;
00837 }
00838 } else {
00839 Tcl_AppendResult(interp, " measure bond: invalid syntax, no such keyword: ", argvcur, NULL);
00840 return TCL_ERROR;
00841 }
00842 }
00843 }
00844
00845 if ((allframes || frame>=0) && (first>=0 || last>=0)) {
00846 Tcl_AppendResult(interp, "measure bond: Ambiguous syntax: You cannot specify a frame AND a frame range (using first or last).", NULL);
00847 Tcl_AppendResult(interp, "\nUsage:\nmeasure bond {{<atomid1> [<molid1>]} {<atomid2> [<molid2>]}} [molid <default>] [frame <frame|all|last> | first <first> last <last>]", NULL);
00848 return TCL_ERROR;
00849 }
00850
00851 if (allframes) first=0;
00852
00853
00854 if (defmolid<0) defmolid = app->molecule_top();
00855
00856
00857 int i, numelem;
00858 Tcl_Obj **atmmol;
00859 for (i=0; i<numatms; i++) {
00860 if (Tcl_ListObjGetElements(interp, data[i], &numelem, &atmmol) != TCL_OK) {
00861 return TCL_ERROR;
00862 }
00863
00864 if (!numelem) {
00865 Tcl_AppendResult(interp, " measure bond: empty atom index", NULL);
00866 return TCL_ERROR;
00867 }
00868
00869 if (Tcl_GetIntFromObj(interp, atmmol[0], atmid+i) != TCL_OK) {
00870 Tcl_AppendResult(interp, " measure bond: bad atom index", NULL);
00871 return TCL_ERROR;
00872 }
00873
00874 if (numelem==2) {
00875 if (Tcl_GetIntFromObj(interp, atmmol[1], molid+i) != TCL_OK) {
00876 Tcl_AppendResult(interp, " measure bond: bad molid", NULL);
00877 return TCL_ERROR;
00878 }
00879 } else molid[i] = defmolid;
00880 }
00881
00882
00883 ResizeArray<float> gValues(1024);
00884 int ret_val;
00885 ret_val = measure_geom(app->moleculeList, molid, atmid, &gValues,
00886 frame, first, last, defmolid, MEASURE_BOND);
00887 if (ret_val < 0) {
00888 printf("ERROR\n %s\n", measure_error(ret_val));
00889 Tcl_AppendResult(interp, measure_error(ret_val), NULL);
00890 return TCL_ERROR;
00891 }
00892
00893 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00894 int numvalues = gValues.num();
00895 for (int count = 0; count < numvalues; count++) {
00896 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(gValues[count]));
00897 }
00898 Tcl_SetObjResult(interp, tcl_result);
00899
00900 return TCL_OK;
00901 }
00902
00903
00904
00905
00906
00907
00908 static int vmd_measure_rmsfperresidue(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00909 int first = 0;
00910 int last = -1;
00911 int step = 1;
00912
00913 if (argc < 2 || argc > 8) {
00914 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<sel> [first <first>] [last <last>] [step <step>]");
00915 return TCL_ERROR;
00916 }
00917 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL)
00918 );
00919 if (!sel) {
00920 Tcl_AppendResult(interp, "measure rmsfperresidue: no atom selection", NULL);
00921 return TCL_ERROR;
00922 }
00923
00924 int i;
00925 for (i=2; i<argc; i+=2) {
00926 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00927 if (!strupncmp(argvcur, "first", CMDLEN)) {
00928 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00929 Tcl_AppendResult(interp, "measure rmsfperresidue: bad first frame value", NULL);
00930 return TCL_ERROR;
00931 }
00932 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00933 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00934 Tcl_AppendResult(interp, "measure rmsfperresidue: bad last frame value", NULL);
00935 return TCL_ERROR;
00936 }
00937 } else if (!strupncmp(argvcur, "step", CMDLEN)) {
00938 if (Tcl_GetIntFromObj(interp, objv[i+1], &step) != TCL_OK) {
00939 Tcl_AppendResult(interp, "measure rmsfperresidue: bad frame step value", NULL);
00940 return TCL_ERROR;
00941 }
00942 } else {
00943 Tcl_AppendResult(interp, "measure rmsfperresidue: invalid syntax, no such keyword: ", argvcur, NULL);
00944 return TCL_ERROR;
00945 }
00946 }
00947
00948 float *rmsf = new float[sel->selected];
00949 int ret_val = measure_rmsf_perresidue(sel, app->moleculeList, first, last, step, rmsf);
00950 if (ret_val < 0) {
00951 Tcl_AppendResult(interp, "measure rmsfperresidue: ", measure_error(ret_val), NULL);
00952 delete [] rmsf;
00953 return TCL_ERROR;
00954 }
00955
00956 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00957 for (i=0; i<ret_val; i++) {
00958 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(rmsf[i]));
00959 }
00960 Tcl_SetObjResult(interp, tcl_result);
00961 delete [] rmsf;
00962
00963 return TCL_OK;
00964 }
00965
00966
00967
00968
00969
00970 static int vmd_measure_rmsf(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00971 int first = 0;
00972 int last = -1;
00973 int step = 1;
00974
00975 if (argc < 2 || argc > 8) {
00976 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<sel> [first <first>] [last <last>] [step <step>]");
00977 return TCL_ERROR;
00978 }
00979 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL)
00980 );
00981 if (!sel) {
00982 Tcl_AppendResult(interp, "measure rmsf: no atom selection", NULL);
00983 return TCL_ERROR;
00984 }
00985
00986 int i;
00987 for (i=2; i<argc; i+=2) {
00988 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
00989 if (!strupncmp(argvcur, "first", CMDLEN)) {
00990 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
00991 Tcl_AppendResult(interp, "measure rmsf: bad first frame value", NULL);
00992 return TCL_ERROR;
00993 }
00994 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
00995 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
00996 Tcl_AppendResult(interp, "measure rmsf: bad last frame value", NULL);
00997 return TCL_ERROR;
00998 }
00999 } else if (!strupncmp(argvcur, "step", CMDLEN)) {
01000 if (Tcl_GetIntFromObj(interp, objv[i+1], &step) != TCL_OK) {
01001 Tcl_AppendResult(interp, "measure rmsf: bad frame step value", NULL);
01002 return TCL_ERROR;
01003 }
01004 } else {
01005 Tcl_AppendResult(interp, "measure rmsf: invalid syntax, no such keyword: ", argvcur, NULL);
01006 return TCL_ERROR;
01007 }
01008 }
01009
01010 float *rmsf = new float[sel->selected];
01011 int ret_val = measure_rmsf(sel, app->moleculeList, first, last, step, rmsf);
01012 if (ret_val < 0) {
01013 Tcl_AppendResult(interp, "measure rmsf: ", measure_error(ret_val), NULL);
01014 delete [] rmsf;
01015 return TCL_ERROR;
01016 }
01017
01018 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
01019 for (i=0; i<sel->selected; i++) {
01020 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(rmsf[i]));
01021 }
01022 Tcl_SetObjResult(interp, tcl_result);
01023
01024 delete [] rmsf;
01025 return TCL_OK;
01026 }
01027
01028
01029
01030 static int vmd_measure_rgyr(VMDApp *app, int argc, Tcl_Obj *const objv[], Tcl_Interp *interp) {
01031 if (argc != 2 && argc != 4) {
01032 Tcl_WrongNumArgs(interp, 2, objv-1,
01033 (char *)"<selection> [weight <weights>]");
01034 return TCL_ERROR;
01035 }
01036 if (argc == 4 && strcmp(Tcl_GetStringFromObj(objv[2],NULL), "weight")) {
01037 Tcl_SetResult(interp, (char *) "measure rgyr: parameter can only be 'weight'", TCL_STATIC);
01038 return TCL_ERROR;
01039 }
01040
01041
01042 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
01043 if (!sel) {
01044 Tcl_SetResult(interp, (char *) "measure rgyr: no atom selection", TCL_STATIC);
01045 return TCL_ERROR;
01046 }
01047
01048
01049 float *weight = new float[sel->selected];
01050 int ret_val = 0;
01051 if (argc == 2) {
01052 ret_val = tcl_get_weights(interp, app, sel, NULL, weight);
01053 } else {
01054 ret_val = tcl_get_weights(interp, app, sel, objv[3], weight);
01055 }
01056 if (ret_val < 0) {
01057 Tcl_AppendResult(interp, "measure rgyr: ", measure_error(ret_val), NULL);
01058 delete [] weight;
01059 return TCL_ERROR;
01060 }
01061
01062 float rgyr;
01063 ret_val = measure_rgyr(sel, app->moleculeList, weight, &rgyr);
01064 delete [] weight;
01065 if (ret_val < 0) {
01066 Tcl_AppendResult(interp, "measure rgyr: ", measure_error(ret_val), NULL);
01067 return TCL_ERROR;
01068 }
01069 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rgyr));
01070 return TCL_OK;
01071 }
01072
01073
01074
01075
01076
01077
01078 static int vmd_measure_minmax(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01079 const float *radii = NULL;
01080 if (argc != 2 && argc != 3) {
01081 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<selection> [-withradii]");
01082 return TCL_ERROR;
01083 }
01084 if (argc == 3 && strcmp(Tcl_GetStringFromObj(objv[2],NULL), "-withradii")) {
01085 Tcl_SetResult(interp, (char *) "measure minmax: parameter can only be '-withradii'", TCL_STATIC);
01086 return TCL_ERROR;
01087 }
01088
01089 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
01090 if (!sel) {
01091 Tcl_AppendResult(interp, "measure minmax: no atom selection", NULL);
01092 return TCL_ERROR;
01093 }
01094
01095 float min_coord[3], max_coord[3];
01096 const float *framepos = sel->coordinates(app->moleculeList);
01097 if (!framepos) return TCL_ERROR;
01098
01099
01100 if (argc == 3) {
01101 Molecule *mol = app->moleculeList->mol_from_id(sel->molid());
01102 radii = mol->extraflt.data("radius");
01103 }
01104
01105 int ret_val = measure_minmax(sel->num_atoms, sel->on, framepos, radii,
01106 min_coord, max_coord);
01107 if (ret_val < 0) {
01108 Tcl_AppendResult(interp, "measure minmax: ", measure_error(ret_val), NULL);
01109 return TCL_ERROR;
01110 }
01111
01112 Tcl_Obj *list1 = Tcl_NewListObj(0, NULL);
01113 Tcl_Obj *list2 = Tcl_NewListObj(0, NULL);
01114 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
01115
01116 Tcl_ListObjAppendElement(interp, list1, Tcl_NewDoubleObj(min_coord[0]));
01117 Tcl_ListObjAppendElement(interp, list1, Tcl_NewDoubleObj(min_coord[1]));
01118 Tcl_ListObjAppendElement(interp, list1, Tcl_NewDoubleObj(min_coord[2]));
01119
01120 Tcl_ListObjAppendElement(interp, list2, Tcl_NewDoubleObj(max_coord[0]));
01121 Tcl_ListObjAppendElement(interp, list2, Tcl_NewDoubleObj(max_coord[1]));
01122 Tcl_ListObjAppendElement(interp, list2, Tcl_NewDoubleObj(max_coord[2]));
01123
01124 Tcl_ListObjAppendElement(interp, tcl_result, list1);
01125 Tcl_ListObjAppendElement(interp, tcl_result, list2);
01126 Tcl_SetObjResult(interp, tcl_result);
01127
01128 return TCL_OK;
01129 }
01130
01131
01132 static int vmd_measure_rmsdperresidue(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01133 if (argc !=3 && argc != 5) {
01134 Tcl_WrongNumArgs(interp, 2, objv-1,
01135 (char *)"<sel1> <sel2> [weight <weights>]");
01136 return TCL_ERROR;
01137 }
01138
01139
01140 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
01141 AtomSel *sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2],NULL));
01142 if (!sel1 || !sel2) {
01143 Tcl_AppendResult(interp, "measure rmsd: no atom selection", NULL);
01144 return TCL_ERROR;
01145 }
01146
01147 if (sel1->selected != sel2->selected) {
01148 Tcl_AppendResult(interp, "measure rmsd: selections must have the same number of atoms", NULL);
01149 return TCL_ERROR;
01150 }
01151 if (!sel1->selected) {
01152 Tcl_AppendResult(interp, "measure rmsd: no atoms selected", NULL);
01153 return TCL_ERROR;
01154 }
01155 float *weight = new float[sel1->selected];
01156 int ret_val = 0;
01157 if (argc == 3) {
01158 ret_val = tcl_get_weights(interp, app, sel1, NULL, weight);
01159 } else {
01160 ret_val = tcl_get_weights(interp, app, sel1, objv[4], weight);
01161 }
01162 if (ret_val < 0) {
01163 Tcl_AppendResult(interp, "measure rmsd: ", measure_error(ret_val), NULL);
01164 delete [] weight;
01165 return TCL_ERROR;
01166 }
01167
01168
01169 float *rmsd = new float[sel1->selected];
01170 int rc = measure_rmsd_perresidue(sel1, sel2, app->moleculeList,
01171 sel1->selected, weight, rmsd);
01172 if (rc < 0) {
01173 Tcl_AppendResult(interp, "measure rmsd: ", measure_error(rc), NULL);
01174 delete [] weight;
01175 delete [] rmsd;
01176 return TCL_ERROR;
01177 }
01178 delete [] weight;
01179 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
01180 int i;
01181 for (i=0; i<rc; i++) {
01182 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(rmsd[i]));
01183 }
01184 delete [] rmsd;
01185 Tcl_SetObjResult(interp, tcl_result);
01186
01187 return TCL_OK;
01188 }
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208 static int vmd_measure_rmsd(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp)
01209 {
01210 if (argc !=3 && argc != 5) {
01211 Tcl_WrongNumArgs(interp, 2, objv-1,
01212 (char *)"<sel1> <sel2> [weight <weights>]");
01213 return TCL_ERROR;
01214 }
01215
01216
01217 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
01218 AtomSel *sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2],NULL));
01219 if (!sel1 || !sel2) {
01220 Tcl_AppendResult(interp, "measure rmsd: no atom selection", NULL);
01221 return TCL_ERROR;
01222 }
01223
01224 if (sel1->selected != sel2->selected) {
01225 Tcl_AppendResult(interp, "measure rmsd: selections must have the same number of atoms", NULL);
01226 return TCL_ERROR;
01227 }
01228 if (!sel1->selected) {
01229 Tcl_AppendResult(interp, "measure rmsd: no atoms selected", NULL);
01230 return TCL_ERROR;
01231 }
01232
01233 float *weight = new float[sel1->selected];
01234 int ret_val = 0;
01235 if (argc == 3) {
01236 ret_val = tcl_get_weights(interp, app, sel1, NULL, weight);
01237 } else {
01238 ret_val = tcl_get_weights(interp, app, sel1, objv[4], weight);
01239 }
01240 if (ret_val < 0) {
01241 Tcl_AppendResult(interp, "measure rmsd: ", measure_error(ret_val), NULL);
01242 delete [] weight;
01243 return TCL_ERROR;
01244 }
01245
01246
01247 float rmsd = 0;
01248 const float *x = sel1->coordinates(app->moleculeList);
01249 const float *y = sel2->coordinates(app->moleculeList);
01250 if (!x || !y) {
01251 delete [] weight;
01252 return TCL_ERROR;
01253 }
01254
01255 ret_val = measure_rmsd(sel1, sel2, sel1->selected, x, y, weight, &rmsd);
01256 delete [] weight;
01257 if (ret_val < 0) {
01258 Tcl_AppendResult(interp, "measure rmsd: ", measure_error(ret_val), NULL);
01259 return TCL_ERROR;
01260 }
01261 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rmsd));
01262
01263 return TCL_OK;
01264 }
01265
01266
01268
01269 static int vmd_measure_rmsd_qcp(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01270 if (argc !=3 && argc != 5) {
01271 Tcl_WrongNumArgs(interp, 2, objv-1,
01272 (char *)"<sel1> <sel2> [weight <weights>]");
01273 return TCL_ERROR;
01274 }
01275
01276 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
01277 AtomSel *sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2],NULL));
01278 if (!sel1 || !sel2) {
01279 Tcl_AppendResult(interp, "measure rmsd: no atom selection", NULL);
01280 return TCL_ERROR;
01281 }
01282
01283 if (sel1->selected != sel2->selected) {
01284 Tcl_AppendResult(interp, "measure rmsd: selections must have the same number of atoms", NULL);
01285 return TCL_ERROR;
01286 }
01287 if (!sel1->selected) {
01288 Tcl_AppendResult(interp, "measure rmsd: no atoms selected", NULL);
01289 return TCL_ERROR;
01290 }
01291 float *weight = new float[sel1->selected];
01292 {
01293 int ret_val;
01294 if (argc == 3) {
01295 ret_val = tcl_get_weights(interp, app, sel1, NULL, weight);
01296 } else {
01297 ret_val = tcl_get_weights(interp, app, sel1, objv[4], weight);
01298 }
01299 if (ret_val < 0) {
01300 Tcl_AppendResult(interp, "measure rmsd: ", measure_error(ret_val), NULL);
01301 delete [] weight;
01302 return TCL_ERROR;
01303 }
01304 }
01305
01306
01307 {
01308 float rmsd = 0;
01309 const float *x = sel1->coordinates(app->moleculeList);
01310 const float *y = sel2->coordinates(app->moleculeList);
01311 if (!x || !y) {
01312 delete [] weight;
01313 return TCL_ERROR;
01314 }
01315 int ret_val = measure_rmsd_qcp(app, sel1, sel2, sel1->selected, x, y, weight, &rmsd);
01316 delete [] weight;
01317 if (ret_val < 0) {
01318 Tcl_AppendResult(interp, "measure rmsd: ", measure_error(ret_val), NULL);
01319 return TCL_ERROR;
01320 }
01321 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rmsd));
01322 }
01323 return TCL_OK;
01324 }
01325
01326
01328
01329 static int vmd_measure_rmsdmat_qcp(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01330 int first = 0;
01331 int last = -1;
01332 int step = 1;
01333
01334 if (argc < 2 || argc > 9) {
01335 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> [weight <weights>] [first <first>] [last <last>] [step <step>]");
01336 return TCL_ERROR;
01337 }
01338 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL)
01339 );
01340 if (!sel) {
01341 Tcl_AppendResult(interp, "measure rmsdmat_qcp: no atom selection", NULL);
01342 return TCL_ERROR;
01343 }
01344
01345 int i;
01346 for (i=2; i<argc; i+=2) {
01347 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
01348 if (!strupncmp(argvcur, "first", CMDLEN)) {
01349 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
01350 Tcl_AppendResult(interp, "measure rmsdmat_qcp: bad first frame value", NULL);
01351 return TCL_ERROR;
01352 }
01353 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
01354 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
01355 Tcl_AppendResult(interp, "measure rmsdmat_qcp: bad last frame value", NULL);
01356 return TCL_ERROR;
01357 }
01358 } else if (!strupncmp(argvcur, "step", CMDLEN)) {
01359 if (Tcl_GetIntFromObj(interp, objv[i+1], &step) != TCL_OK) {
01360 Tcl_AppendResult(interp, "measure rmsdmat_qcp: bad frame step value", NULL);
01361 return TCL_ERROR;
01362 }
01363 } else {
01364 Tcl_AppendResult(interp, "measure rmsdmat_qcp: invalid syntax, no such keyword: ", argvcur, NULL);
01365 return TCL_ERROR;
01366 }
01367 }
01368
01369 float *weight = NULL;
01370 if (0) {
01371 weight = new float[sel->selected];
01372 int ret_val;
01373 if (argc == 2) {
01374 ret_val = tcl_get_weights(interp, app, sel, NULL, weight);
01375 } else {
01376 ret_val = tcl_get_weights(interp, app, sel, objv[3], weight);
01377 }
01378
01379 if (ret_val < 0) {
01380 Tcl_AppendResult(interp, "measure rmsdmat_qcp: ", measure_error(ret_val),
01381 NULL);
01382 delete [] weight;
01383 return TCL_ERROR;
01384 }
01385 }
01386
01387
01388 if (last < 0)
01389 last = app->molecule_numframes(sel->molid()) - 1;
01390 int framecount = (last - first + 1) / step;
01391 float *rmsdmat = (float *) calloc(1, framecount * framecount * sizeof(float));
01392
01393
01394 int ret_val = measure_rmsdmat_qcp(app, sel, app->moleculeList,
01395 sel->selected, weight,
01396 first, last, step, rmsdmat);
01397 delete [] weight;
01398
01399 if (ret_val < 0) {
01400 Tcl_AppendResult(interp, "measure rmsdmat_qcp: ", measure_error(ret_val), NULL);
01401 return TCL_ERROR;
01402 }
01403
01404 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
01405 long j;
01406 for (j=0; j<framecount; j++) {
01407 Tcl_Obj *rmsdlist = Tcl_NewListObj(0, NULL);
01408 for (i=0; i<framecount; i++) {
01409 Tcl_ListObjAppendElement(interp, rmsdlist,
01410 Tcl_NewDoubleObj(rmsdmat[j*framecount + i]));
01411 }
01412 Tcl_ListObjAppendElement(interp, tcl_result, rmsdlist);
01413 }
01414 Tcl_SetObjResult(interp, tcl_result);
01415
01416 free(rmsdmat);
01417
01418 return TCL_OK;
01419 }
01420
01421
01423
01424
01425
01426 static int vmd_measure_rmsdmat_qcp_ooc(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01427 int first = 0;
01428 int last = -1;
01429 int step = 1;
01430 int i;
01431 float *weight = NULL;
01432 int nfiles = 0;
01433 const char **trjfileset = NULL;
01434
01435 if (argc < 2) {
01436 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> [weight <weights>] [first <first>] [last <last>] [step <step>] files [file1] [fileN]");
01437 return TCL_ERROR;
01438 }
01439 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL)
01440 );
01441 if (!sel) {
01442 Tcl_AppendResult(interp, "measure rmsdmat_qcp: no atom selection", NULL);
01443 return TCL_ERROR;
01444 }
01445
01446 for (i=2; i<argc; i+=2) {
01447 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
01448 if (!strupncmp(argvcur, "first", CMDLEN)) {
01449 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
01450 Tcl_AppendResult(interp, "measure rmsdmat_qcp_ooc: bad first frame value", NULL);
01451 return TCL_ERROR;
01452 }
01453 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
01454 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
01455 Tcl_AppendResult(interp, "measure rmsdmat_qcp_ooc: bad last frame value", NULL);
01456 return TCL_ERROR;
01457 }
01458 } else if (!strupncmp(argvcur, "step", CMDLEN)) {
01459 if (Tcl_GetIntFromObj(interp, objv[i+1], &step) != TCL_OK) {
01460 Tcl_AppendResult(interp, "measure rmsdmat_qcp_ooc: bad frame step value", NULL);
01461 return TCL_ERROR;
01462 }
01463 } else if (!strupncmp(argvcur, "files", CMDLEN)) {
01464 int list_num;
01465 Tcl_Obj **list_data;
01466 if (Tcl_ListObjGetElements(interp, objv[i+1], &list_num, &list_data) != TCL_OK) {
01467 Tcl_AppendResult(interp, "measure rmsdmat_qcp_ooc: bad trajectory file list", NULL);
01468 return TCL_ERROR;
01469 }
01470
01471 int f;
01472 nfiles = list_num;
01473 trjfileset = (const char **) calloc(1, nfiles * sizeof(const char *));
01474 for (f=0; f<nfiles; f++) {
01475 trjfileset[f] = Tcl_GetStringFromObj(list_data[f], NULL);
01476 printf("File[%d] '%s'\n", f, trjfileset[f]);
01477 }
01478 } else {
01479 Tcl_AppendResult(interp, "measure rmsdmat_qcp_ooc: invalid syntax, no such keyword: ", argvcur, NULL);
01480 return TCL_ERROR;
01481 }
01482 }
01483
01484 #if 0
01485 if (0) {
01486 weight = new float[sel->selected];
01487 int ret_val;
01488 if (argc == 2) {
01489 ret_val = tcl_get_weights(interp, app, sel, NULL, weight);
01490 } else {
01491 ret_val = tcl_get_weights(interp, app, sel, objv[3], weight);
01492 }
01493
01494 if (ret_val < 0) {
01495 Tcl_AppendResult(interp, "measure rmsdmat_qcp: ", measure_error(ret_val),
01496 NULL);
01497 delete [] weight;
01498 return TCL_ERROR;
01499 }
01500 }
01501 #endif
01502
01503
01504 float *rmsdmat = NULL;
01505 int framecount = 0;
01506 int ret_val = measure_rmsdmat_qcp_ooc(app, sel, app->moleculeList,
01507 nfiles, trjfileset,
01508 sel->selected, weight,
01509 first, last, step,
01510 framecount, rmsdmat);
01511 delete [] weight;
01512
01513 if (ret_val < 0) {
01514 Tcl_AppendResult(interp, "measure rmsdmat_qcp_ooc: ", measure_error(ret_val), NULL);
01515 return TCL_ERROR;
01516 }
01517
01518 #if 0
01519 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
01520 long j;
01521 for (j=0; j<framecount; j++) {
01522 Tcl_Obj *rmsdlist = Tcl_NewListObj(0, NULL);
01523 for (i=0; i<framecount; i++) {
01524 Tcl_ListObjAppendElement(interp, rmsdlist,
01525 Tcl_NewDoubleObj(rmsdmat[j*framecount + i]));
01526 }
01527 Tcl_ListObjAppendElement(interp, tcl_result, rmsdlist);
01528 }
01529 Tcl_SetObjResult(interp, tcl_result);
01530 #endif
01531
01532 if (trjfileset != NULL)
01533 free(trjfileset);
01534
01535 if (rmsdmat != NULL)
01536 free(rmsdmat);
01537
01538 return TCL_OK;
01539 }
01540
01541
01542
01544
01545 static int vmd_measure_fit(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp)
01546 {
01547 AtomSel *sel1, *sel2;
01548 int *order = NULL;
01549 float *weight = NULL;
01550 int rc;
01551
01552 if (argc != 3 && argc != 5
01553 && argc != 7) {
01554 Tcl_WrongNumArgs(interp, 2, objv-1,
01555 (char *)"<sel1> <sel2> [weight <weights>] [order <index list>]");
01556 return TCL_ERROR;
01557 } else if (argc == 5
01558 && strcmp("weight", Tcl_GetStringFromObj(objv[3], NULL))
01559 && strcmp("order", Tcl_GetStringFromObj(objv[3], NULL))) {
01560 Tcl_WrongNumArgs(interp, 2, objv-1,
01561 (char *)"<sel1> <sel2> [weight <weights>] [order <index list>]");
01562 return TCL_ERROR;
01563 } else if (argc == 7 &&
01564 (strcmp("weight", Tcl_GetStringFromObj(objv[3], NULL)) ||
01565 strcmp("order", Tcl_GetStringFromObj(objv[5], NULL)))) {
01566 Tcl_WrongNumArgs(interp, 2, objv-1,
01567 (char *)"<sel1> <sel2> [weight <weights>] [order <index list>]");
01568 return TCL_ERROR;
01569 }
01570
01571
01572 sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
01573 sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2],NULL));
01574
01575 if (!sel1 || !sel2) {
01576 Tcl_AppendResult(interp, "measure fit: no atom selection", NULL);
01577 return TCL_ERROR;
01578 }
01579
01580 int num = sel1->selected;
01581 if (!num) {
01582 Tcl_AppendResult(interp, "measure fit: no atoms selected", NULL);
01583 return TCL_ERROR;
01584 }
01585 if (num != sel2->selected) {
01586 Tcl_AppendResult(interp, "measure fit: selections must have the same number of atoms", NULL);
01587 return TCL_ERROR;
01588 }
01589
01590
01591 weight = new float[num];
01592 if (argc > 3 && !strcmp("weight", Tcl_GetStringFromObj(objv[3], NULL))) {
01593
01594 rc = tcl_get_weights(interp, app, sel1, objv[4], weight);
01595 } else {
01596
01597 rc = tcl_get_weights(interp, app, sel1, NULL, weight);
01598 }
01599 if (rc < 0) {
01600 Tcl_AppendResult(interp, "measure fit: ", measure_error(rc), NULL);
01601 delete [] weight;
01602 return TCL_ERROR;
01603 }
01604
01605
01606 int orderparam = 0;
01607 if (argc == 5 && !strcmp("order", Tcl_GetStringFromObj(objv[3], NULL))) {
01608 orderparam = 4;
01609 } else if (argc == 7 && !strcmp("order", Tcl_GetStringFromObj(objv[5], NULL))) {
01610 orderparam = 6;
01611 }
01612
01613 if (orderparam != 0) {
01614
01615 order = new int[num];
01616 rc = tcl_get_orders(interp, num, objv[orderparam], order);
01617 if (rc < 0) {
01618 Tcl_AppendResult(interp, "measure fit: ", measure_error(rc), NULL);
01619 delete [] order;
01620 return TCL_ERROR;
01621 }
01622 }
01623
01624
01625 Matrix4 T;
01626 const float *x = sel1->coordinates(app->moleculeList);
01627 const float *y = sel2->coordinates(app->moleculeList);
01628
01629 int ret_val = MEASURE_ERR_NOMOLECULE;
01630 if (x && y)
01631 ret_val = measure_fit(sel1, sel2, x, y, weight, order, &T);
01632
01633 delete [] weight;
01634
01635 if (order != NULL)
01636 delete [] order;
01637
01638 if (ret_val < 0) {
01639 Tcl_AppendResult(interp, "measure fit: ", measure_error(ret_val), NULL);
01640 return TCL_ERROR;
01641 }
01642
01643
01644 tcl_append_matrix(interp, T.mat);
01645 return TCL_OK;
01646 }
01647
01649
01650 static int vmd_measure_inverse(int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01651
01652 if (argc != 2) {
01653 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<matrix>");
01654 return TCL_ERROR;
01655 }
01656
01657 Matrix4 inv;
01658 if (tcl_get_matrix("measure inverse: ",interp,objv[1],inv.mat) != TCL_OK) {
01659 return TCL_ERROR;
01660 }
01661 if (inv.inverse()) {
01662 Tcl_AppendResult(interp, "Singular Matrix; inverse not computed", NULL);
01663 return TCL_ERROR;
01664 }
01665 tcl_append_matrix(interp, inv.mat);
01666 return TCL_OK;
01667 }
01668
01669
01670 static int vmd_measure_contacts(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01671
01672
01673 if (argc != 3 && argc != 4) {
01674 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<cutoff> <sel1> [<sel2>]");
01675 return TCL_ERROR;
01676 }
01677 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2],NULL));
01678 if (!sel1) {
01679 Tcl_AppendResult(interp, "measure contacts: no atom selection", NULL);
01680 return TCL_ERROR;
01681 }
01682 AtomSel *sel2 = NULL;
01683 if (argc == 4) {
01684 sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[3],NULL));
01685 if (!sel2) {
01686 Tcl_AppendResult(interp, "measure contacts: no atom selection", NULL);
01687 return TCL_ERROR;
01688 }
01689 }
01690 if (!sel2) sel2 = sel1;
01691
01692 double cutoff;
01693 if (Tcl_GetDoubleFromObj(interp, objv[1], &cutoff) != TCL_OK)
01694 return TCL_ERROR;
01695
01696 const float *pos1 = sel1->coordinates(app->moleculeList);
01697 const float *pos2 = sel2->coordinates(app->moleculeList);
01698 if (!pos1 || !pos2) {
01699 Tcl_AppendResult(interp, "measure contacts: error, molecule contains no coordinates", NULL);
01700 return TCL_ERROR;
01701 }
01702 Molecule *mol1 = app->moleculeList->mol_from_id(sel1->molid());
01703 Molecule *mol2 = app->moleculeList->mol_from_id(sel2->molid());
01704
01705 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) * 27L);
01706 GridSearchPair *p, *tmp;
01707 Tcl_Obj *list1 = Tcl_NewListObj(0, NULL);
01708 Tcl_Obj *list2 = Tcl_NewListObj(0, NULL);
01709 for (p=pairlist; p != NULL; p=tmp) {
01710
01711 MolAtom *a1 = mol1->atom(p->ind1);
01712 if (mol1 != mol2 || !a1->bonded(p->ind2)) {
01713 Tcl_ListObjAppendElement(interp, list1, Tcl_NewIntObj(p->ind1));
01714 Tcl_ListObjAppendElement(interp, list2, Tcl_NewIntObj(p->ind2));
01715 }
01716 tmp = p->next;
01717 free(p);
01718 }
01719 Tcl_Obj *result = Tcl_NewListObj(0, NULL);
01720 Tcl_ListObjAppendElement(interp, result, list1);
01721 Tcl_ListObjAppendElement(interp, result, list2);
01722 Tcl_SetObjResult(interp, result);
01723 return TCL_OK;
01724 }
01725
01726
01727
01728
01729 static int vmd_measure_gofr(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01730 int i;
01731
01732 double rmax=10.0;
01733 double delta=0.1;
01734 int usepbc=0;
01735 int selupdate=0;
01736 int first=-1, last=-1, step=1;
01737 int rc;
01738
01739
01740 const char *argerrmsg = "<sel1> <sel2> [delta <value>] [rmax <value>] [usepbc <bool>] [selupdate <bool>] [first <first>] [last <last>] [step <step>]";
01741
01742
01743 if ((argc < 3) || (argc > 17) || (argc % 2 == 0) ) {
01744 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
01745 return TCL_ERROR;
01746 }
01747
01748
01749 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1], NULL));
01750 if (!sel1) {
01751 Tcl_AppendResult(interp, "measure gofr: invalid first atom selection", NULL);
01752 return TCL_ERROR;
01753 }
01754
01755 AtomSel *sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2], NULL));
01756 if (!sel2) {
01757 Tcl_AppendResult(interp, "measure gofr: invalid second atom selection", NULL);
01758 return TCL_ERROR;
01759 }
01760
01761
01762 for (i=3; i<argc; i+=2) {
01763 const char *opt = Tcl_GetStringFromObj(objv[i], NULL);
01764 if (i==(argc-1)) {
01765 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
01766 return TCL_ERROR;
01767 }
01768 if (!strcmp(opt, "delta")) {
01769 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &delta) != TCL_OK)
01770 return TCL_ERROR;
01771 if (delta <= 0.0) {
01772 Tcl_AppendResult(interp, "measure gofr: invalid 'delta' value", NULL);
01773 return TCL_ERROR;
01774 }
01775 } else if (!strcmp(opt, "rmax")) {
01776 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &rmax) != TCL_OK)
01777 return TCL_ERROR;
01778 if (rmax <= 0.0) {
01779 Tcl_AppendResult(interp, "measure gofr: invalid 'rmax' value", NULL);
01780 return TCL_ERROR;
01781 }
01782 } else if (!strcmp(opt, "usepbc")) {
01783 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &usepbc) != TCL_OK)
01784 return TCL_ERROR;
01785 } else if (!strcmp(opt, "selupdate")) {
01786 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &selupdate) != TCL_OK)
01787 return TCL_ERROR;
01788 } else if (!strcmp(opt, "first")) {
01789 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK)
01790 return TCL_ERROR;
01791 } else if (!strcmp(opt, "last")) {
01792 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK)
01793 return TCL_ERROR;
01794 } else if (!strcmp(opt, "step")) {
01795 if (Tcl_GetIntFromObj(interp, objv[i+1], &step) != TCL_OK)
01796 return TCL_ERROR;
01797 } else {
01798 Tcl_AppendResult(interp, "unknown keyword '", opt, "'. usage: measure gofr ", argerrmsg, NULL);
01799 return TCL_ERROR;
01800 }
01801 }
01802
01803
01804 int count_h = (int)(rmax / delta + 1.0);
01805 double *gofr = new double[count_h];
01806 double *numint = new double[count_h];
01807 double *histog = new double[count_h];
01808 int *framecntr = new int[3];
01809
01810
01811 rc = measure_gofr(sel1, sel2, app->moleculeList,
01812 count_h, gofr, numint, histog,
01813 (float) delta,
01814 first, last, step, framecntr,
01815 usepbc, selupdate);
01816
01817
01818 if (rc != MEASURE_NOERR) {
01819 Tcl_AppendResult(interp, "measure gofr: error during g(r) calculation.", NULL);
01820 return TCL_ERROR;
01821 }
01822
01823
01824
01825 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
01826 Tcl_Obj *tcl_rlist = Tcl_NewListObj(0, NULL);
01827 Tcl_Obj *tcl_gofr = Tcl_NewListObj(0, NULL);
01828 Tcl_Obj *tcl_numint = Tcl_NewListObj(0, NULL);
01829 Tcl_Obj *tcl_histog = Tcl_NewListObj(0, NULL);
01830 Tcl_Obj *tcl_frames = Tcl_NewListObj(0, NULL);
01831
01832
01833 for (i=0; i<count_h; i++) {
01834 Tcl_ListObjAppendElement(interp, tcl_rlist, Tcl_NewDoubleObj(delta * ((double)i + 0.5)));
01835 Tcl_ListObjAppendElement(interp, tcl_gofr, Tcl_NewDoubleObj(gofr[i]));
01836 Tcl_ListObjAppendElement(interp, tcl_numint, Tcl_NewDoubleObj(numint[i]));
01837 Tcl_ListObjAppendElement(interp, tcl_histog, Tcl_NewDoubleObj(histog[i]));
01838 }
01839
01840
01841
01842 Tcl_ListObjAppendElement(interp, tcl_frames, Tcl_NewIntObj(framecntr[0]));
01843 Tcl_ListObjAppendElement(interp, tcl_frames, Tcl_NewIntObj(framecntr[1]));
01844 Tcl_ListObjAppendElement(interp, tcl_frames, Tcl_NewIntObj(framecntr[2]));
01845
01846
01847 Tcl_ListObjAppendElement(interp, tcl_result, tcl_rlist);
01848 Tcl_ListObjAppendElement(interp, tcl_result, tcl_gofr);
01849 Tcl_ListObjAppendElement(interp, tcl_result, tcl_numint);
01850 Tcl_ListObjAppendElement(interp, tcl_result, tcl_histog);
01851 Tcl_ListObjAppendElement(interp, tcl_result, tcl_frames);
01852 Tcl_SetObjResult(interp, tcl_result);
01853
01854 delete [] gofr;
01855 delete [] numint;
01856 delete [] histog;
01857 delete [] framecntr;
01858 return TCL_OK;
01859 }
01860
01861
01862
01863
01864 static int vmd_measure_rdf(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01865 int i;
01866
01867 double rmax=10.0;
01868 double delta=0.1;
01869 int usepbc=0;
01870 int selupdate=0;
01871 int first=-1, last=-1, step=1;
01872 int rc;
01873
01874
01875 const char *argerrmsg = "<sel1> <sel2> [delta <value>] [rmax <value>] [usepbc <bool>] [selupdate <bool>] [first <first>] [last <last>] [step <step>]";
01876
01877
01878 if ((argc < 3) || (argc > 17) || (argc % 2 == 0) ) {
01879 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
01880 return TCL_ERROR;
01881 }
01882
01883
01884 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1], NULL));
01885 if (!sel1) {
01886 Tcl_AppendResult(interp, "measure rdf: invalid first atom selection", NULL);
01887 return TCL_ERROR;
01888 }
01889
01890 AtomSel *sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2], NULL));
01891 if (!sel2) {
01892 Tcl_AppendResult(interp, "measure rdf: invalid second atom selection", NULL);
01893 return TCL_ERROR;
01894 }
01895
01896
01897 for (i=3; i<argc; i+=2) {
01898 const char *opt = Tcl_GetStringFromObj(objv[i], NULL);
01899 if (i==(argc-1)) {
01900 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
01901 return TCL_ERROR;
01902 }
01903 if (!strcmp(opt, "delta")) {
01904 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &delta) != TCL_OK)
01905 return TCL_ERROR;
01906 if (delta <= 0.0) {
01907 Tcl_AppendResult(interp, "measure rdf: invalid 'delta' value", NULL);
01908 return TCL_ERROR;
01909 }
01910 } else if (!strcmp(opt, "rmax")) {
01911 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &rmax) != TCL_OK)
01912 return TCL_ERROR;
01913 if (rmax <= 0.0) {
01914 Tcl_AppendResult(interp, "measure rdf: invalid 'rmax' value", NULL);
01915 return TCL_ERROR;
01916 }
01917 } else if (!strcmp(opt, "usepbc")) {
01918 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &usepbc) != TCL_OK)
01919 return TCL_ERROR;
01920 } else if (!strcmp(opt, "selupdate")) {
01921 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &selupdate) != TCL_OK)
01922 return TCL_ERROR;
01923 } else if (!strcmp(opt, "first")) {
01924 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK)
01925 return TCL_ERROR;
01926 } else if (!strcmp(opt, "last")) {
01927 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK)
01928 return TCL_ERROR;
01929 } else if (!strcmp(opt, "step")) {
01930 if (Tcl_GetIntFromObj(interp, objv[i+1], &step) != TCL_OK)
01931 return TCL_ERROR;
01932 } else {
01933 Tcl_AppendResult(interp, "unknown keyword '", opt, "'. usage: measure rdf ", argerrmsg, NULL);
01934 return TCL_ERROR;
01935 }
01936 }
01937
01938
01939 int count_h = (int)(rmax / delta + 1.0);
01940 double *gofr = new double[count_h];
01941 double *numint = new double[count_h];
01942 double *histog = new double[count_h];
01943 int *framecntr = new int[3];
01944
01945
01946 rc = measure_rdf(app, sel1, sel2, app->moleculeList,
01947 count_h, gofr, numint, histog,
01948 (float) delta,
01949 first, last, step, framecntr,
01950 usepbc, selupdate);
01951
01952
01953 if (rc != MEASURE_NOERR) {
01954 Tcl_AppendResult(interp, "measure rdf: error during rdf calculation.", NULL);
01955 return TCL_ERROR;
01956 }
01957
01958
01959
01960 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
01961 Tcl_Obj *tcl_rlist = Tcl_NewListObj(0, NULL);
01962 Tcl_Obj *tcl_gofr = Tcl_NewListObj(0, NULL);
01963 Tcl_Obj *tcl_numint = Tcl_NewListObj(0, NULL);
01964 Tcl_Obj *tcl_histog = Tcl_NewListObj(0, NULL);
01965 Tcl_Obj *tcl_frames = Tcl_NewListObj(0, NULL);
01966
01967
01968 for (i=0; i<count_h; i++) {
01969 Tcl_ListObjAppendElement(interp, tcl_rlist, Tcl_NewDoubleObj(delta * ((double)i + 0.5)));
01970 Tcl_ListObjAppendElement(interp, tcl_gofr, Tcl_NewDoubleObj(gofr[i]));
01971 Tcl_ListObjAppendElement(interp, tcl_numint, Tcl_NewDoubleObj(numint[i]));
01972 Tcl_ListObjAppendElement(interp, tcl_histog, Tcl_NewDoubleObj(histog[i]));
01973 }
01974
01975
01976
01977 Tcl_ListObjAppendElement(interp, tcl_frames, Tcl_NewIntObj(framecntr[0]));
01978 Tcl_ListObjAppendElement(interp, tcl_frames, Tcl_NewIntObj(framecntr[1]));
01979 Tcl_ListObjAppendElement(interp, tcl_frames, Tcl_NewIntObj(framecntr[2]));
01980
01981
01982 Tcl_ListObjAppendElement(interp, tcl_result, tcl_rlist);
01983 Tcl_ListObjAppendElement(interp, tcl_result, tcl_gofr);
01984 Tcl_ListObjAppendElement(interp, tcl_result, tcl_numint);
01985 Tcl_ListObjAppendElement(interp, tcl_result, tcl_histog);
01986 Tcl_ListObjAppendElement(interp, tcl_result, tcl_frames);
01987 Tcl_SetObjResult(interp, tcl_result);
01988
01989 delete [] gofr;
01990 delete [] numint;
01991 delete [] histog;
01992 delete [] framecntr;
01993 return TCL_OK;
01994 }
01995
01996
01998 static int vmd_measure_cluster(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
01999 int i,j;
02000
02001 int algorithm=0;
02002 int likeness=MEASURE_DIST_FITRMSD;
02003 int numcluster=5;
02004 double cutoff=1.0;
02005 float *weights=NULL;
02006 int selupdate=0;
02007 int first=0, last=-1, step=1;
02008 int rc;
02009
02010
02011 const char *argerrmsg = "<sel> [num <#clusters>] [distfunc <flag>] "
02012 "[cutoff <cutoff>] [first <first>] [last <last>] [step <step>] "
02013 "[selupdate <bool>] [weight <weights>]";
02014
02015
02016 if ((argc < 2) || (argc > 19) || ((argc-1) % 2 == 0) ) {
02017 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
02018 return TCL_ERROR;
02019 }
02020
02021
02022 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1], NULL));
02023 if (!sel) {
02024 Tcl_AppendResult(interp, "measure cluster: invalid atom selection", NULL);
02025 return TCL_ERROR;
02026 }
02027 if (!app->molecule_valid_id(sel->molid())) return MEASURE_ERR_NOMOLECULE;
02028
02029
02030 for (i=2; i<argc; i+=2) {
02031 const char *opt = Tcl_GetStringFromObj(objv[i], NULL);
02032 if (i==(argc-1)) {
02033 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
02034 return TCL_ERROR;
02035 }
02036 if (!strcmp(opt, "num")) {
02037 if (Tcl_GetIntFromObj(interp, objv[i+1], &numcluster) != TCL_OK)
02038 return TCL_ERROR;
02039 if (numcluster < 1) {
02040 Tcl_AppendResult(interp, "measure cluster: invalid 'num' value (cannot be smaller than 1)", NULL);
02041 return TCL_ERROR;
02042 }
02043 } else if (!strcmp(opt, "cutoff")) {
02044 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &cutoff) != TCL_OK)
02045 return TCL_ERROR;
02046 if (cutoff <= 0.0) {
02047 Tcl_AppendResult(interp, "measure cluster: invalid 'cutoff' value (should be larger than 0.0)", NULL);
02048 return TCL_ERROR;
02049 }
02050 } else if (!strcmp(opt, "distfunc")) {
02051 char *argstr = Tcl_GetStringFromObj(objv[i+1], NULL);
02052 if (!strcmp(argstr,"rmsd")) {
02053 likeness = MEASURE_DIST_RMSD;
02054 } else if (!strcmp(argstr,"fitrmsd")) {
02055 likeness = MEASURE_DIST_FITRMSD;
02056 } else if (!strcmp(argstr,"rgyrd")) {
02057 likeness = MEASURE_DIST_RGYRD;
02058 } else {
02059 Tcl_AppendResult(interp, "measure cluster: unknown distance function (supported are 'rmsd', 'rgyrd' and 'fitrmsd')", NULL);
02060 return TCL_ERROR;
02061 }
02062 } else if (!strcmp(opt, "selupdate")) {
02063 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &selupdate) != TCL_OK)
02064 return TCL_ERROR;
02065 } else if (!strcmp(opt, "weight")) {
02066
02067
02068
02069
02070 const char *weight_string = Tcl_GetStringFromObj(objv[i+1], NULL);
02071 weights = new float[sel->num_atoms];
02072
02073 if (!weight_string || !strcmp(weight_string, "none")) {
02074 for (j=0; j<sel->num_atoms; j++) weights[j]=1.0f;
02075 } else {
02076
02077 SymbolTable *atomSelParser = app->atomSelParser;
02078
02079
02080 atomsel_ctxt context(atomSelParser,
02081 app->moleculeList->mol_from_id(sel->molid()),
02082 sel->which_frame, NULL);
02083
02084 int fctn = atomSelParser->find_attribute(weight_string);
02085 if (fctn >= 0) {
02086
02087
02088
02089 if (atomSelParser->fctns.data(fctn)->returns_a != SymbolTableElement::IS_FLOAT) {
02090 Tcl_AppendResult(interp, "weight attribute must have floating point values", NULL);
02091 delete [] weights;
02092 return MEASURE_ERR_BADWEIGHTPARM;
02093 }
02094
02095 double *tmp_data = new double[sel->num_atoms];
02096 int *all_on = new int[sel->num_atoms];
02097 for (j=0; j<sel->num_atoms; j++) all_on[j]=1;
02098
02099 atomSelParser->fctns.data(fctn)->keyword_double(
02100 &context, sel->num_atoms, tmp_data, all_on);
02101
02102 for (j=0; j<sel->num_atoms; j++) weights[j] = (float)tmp_data[j];
02103
02104
02105 delete [] tmp_data;
02106 delete [] all_on;
02107 }
02108 }
02109 } else if (!strcmp(opt, "first")) {
02110 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK)
02111 return TCL_ERROR;
02112 } else if (!strcmp(opt, "last")) {
02113 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK)
02114 return TCL_ERROR;
02115 } else if (!strcmp(opt, "step")) {
02116 if (Tcl_GetIntFromObj(interp, objv[i+1], &step) != TCL_OK)
02117 return TCL_ERROR;
02118 } else {
02119 Tcl_AppendResult(interp, "unknown keyword '", opt, "'. usage: measure cluster ", argerrmsg, NULL);
02120 return TCL_ERROR;
02121 }
02122 }
02123
02124
02125 if (!weights) {
02126 weights = new float[sel->num_atoms];
02127 for (j=0; j<sel->num_atoms; j++) weights[j]=1.0f;
02128 }
02129
02130
02131
02132
02133
02134 int *clustersize = new int [numcluster+1];
02135 int **clusterlist = new int *[numcluster+1];
02136
02137
02138 rc = measure_cluster(sel, app->moleculeList, numcluster, algorithm, likeness, cutoff,
02139 clustersize, clusterlist, first, last, step, selupdate, weights);
02140
02141 if (weights) delete [] weights;
02142
02143
02144 if (rc != MEASURE_NOERR) {
02145 Tcl_AppendResult(interp, "measure cluster: error during cluster analysis calculation.", NULL);
02146 return TCL_ERROR;
02147 }
02148
02149
02150
02151 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
02152
02153 for (i=0; i <= numcluster; ++i) {
02154 int j;
02155 Tcl_Obj *tcl_clist = Tcl_NewListObj(0, NULL);
02156 for (j=0; j < clustersize[i]; ++j) {
02157 Tcl_ListObjAppendElement(interp, tcl_clist, Tcl_NewIntObj(clusterlist[i][j]));
02158 }
02159 Tcl_ListObjAppendElement(interp, tcl_result, tcl_clist);
02160 }
02161 Tcl_SetObjResult(interp, tcl_result);
02162
02163
02164 for (i=0; i <= numcluster; ++i)
02165 delete[] clusterlist[i];
02166
02167 delete[] clusterlist;
02168 delete[] clustersize;
02169
02170 return TCL_OK;
02171 }
02172
02174 static int vmd_measure_clustsize(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
02175 int i;
02176
02177 double cutoff=3.0;
02178 char *storesize=NULL;
02179 char *storenum=NULL;
02180 int usepbc=0;
02181 int minsize=2;
02182 int numshared=1;
02183 int rc;
02184
02185
02186 const char *argerrmsg = "<sel> [cutoff <float>] [minsize <num>] [numshared <num>] "
02187 "[usepbc <bool>] [storesize <fieldname>] [storenum <fieldname>]";
02188
02189
02190 if ((argc < 2) || (argc > 13) || ((argc-1) % 2 == 0) ) {
02191 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
02192 return TCL_ERROR;
02193 }
02194
02195
02196 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1], NULL));
02197 if (!sel) {
02198 Tcl_AppendResult(interp, "measure clustsize: invalid atom selection", NULL);
02199 return TCL_ERROR;
02200 }
02201 if (!app->molecule_valid_id(sel->molid())) return MEASURE_ERR_NOMOLECULE;
02202
02203
02204 for (i=2; i<argc; i+=2) {
02205 const char *opt = Tcl_GetStringFromObj(objv[i], NULL);
02206 if (i==(argc-1)) {
02207 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)argerrmsg);
02208 return TCL_ERROR;
02209 } else if (!strcmp(opt, "cutoff")) {
02210 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &cutoff) != TCL_OK)
02211 return TCL_ERROR;
02212 if (cutoff <= 0.0) {
02213 Tcl_AppendResult(interp, "measure clustsize: invalid 'cutoff' value", NULL);
02214 return TCL_ERROR;
02215 }
02216 } else if (!strcmp(opt, "minsize")) {
02217 if (Tcl_GetIntFromObj(interp, objv[i+1], &minsize) != TCL_OK)
02218 return TCL_ERROR;
02219 if (minsize < 2) {
02220 Tcl_AppendResult(interp, "measure clustsize: invalid 'minsize' value", NULL);
02221 return TCL_ERROR;
02222 }
02223 } else if (!strcmp(opt, "numshared")) {
02224 if (Tcl_GetIntFromObj(interp, objv[i+1], &numshared) != TCL_OK)
02225 return TCL_ERROR;
02226 if (numshared < 0) {
02227 Tcl_AppendResult(interp, "measure clustsize: invalid 'numshared' value", NULL);
02228 return TCL_ERROR;
02229 }
02230 } else if (!strcmp(opt, "usepbc")) {
02231 if (Tcl_GetBooleanFromObj(interp, objv[i+1], &usepbc) != TCL_OK)
02232 return TCL_ERROR;
02233 } else if (!strcmp(opt, "storenum")) {
02234 storenum = Tcl_GetStringFromObj(objv[i+1], NULL);
02235 } else if (!strcmp(opt, "storesize")) {
02236 storesize = Tcl_GetStringFromObj(objv[i+1], NULL);
02237 } else {
02238 Tcl_AppendResult(interp, "unknown keyword '", opt, "'. usage: measure clustsize ", argerrmsg, NULL);
02239 return TCL_ERROR;
02240 }
02241 }
02242
02243 if (usepbc) {
02244 Tcl_AppendResult(interp, "measure clustsize: does not support periodic boundaries yet.", NULL);
02245 return TCL_ERROR;
02246 }
02247
02248
02249
02250
02251 int num_selected=sel->selected;
02252 int *clustersize = new int[num_selected];
02253 int *clusternum= new int [num_selected];
02254 int *clusteridx= new int [num_selected];
02255 for (i=0; i < num_selected; i++) {
02256 clustersize[i] = 0;
02257 clusternum[i] = -1;
02258 clusteridx[i] = -1;
02259 }
02260
02261
02262 rc = measure_clustsize(sel, app->moleculeList, cutoff,
02263 clustersize, clusternum, clusteridx,
02264 minsize, numshared, usepbc);
02265
02266
02267 if (rc != MEASURE_NOERR) {
02268 Tcl_AppendResult(interp, "measure clustsize: error during cluster size analysis calculation.", NULL);
02269 return TCL_ERROR;
02270 }
02271
02272
02273 if (storenum || storesize) {
02274
02275 SymbolTable *atomSelParser = app->atomSelParser;
02276 atomsel_ctxt context(atomSelParser,
02277 app->moleculeList->mol_from_id(sel->molid()),
02278 sel->which_frame, NULL);
02279
02280
02281 if (storenum) {
02282 int fctn = atomSelParser->find_attribute(storenum);
02283 if (fctn >= 0) {
02284 if (atomSelParser->fctns.data(fctn)->returns_a == SymbolTableElement::IS_FLOAT) {
02285 double *tmp_data = new double[sel->num_atoms];
02286 int j=0;
02287 for (int i=sel->firstsel; i<=sel->lastsel; i++) {
02288 if (sel->on[i])
02289 tmp_data[i] = (double) clusternum[j++];
02290 }
02291 atomSelParser->fctns.data(fctn)->set_keyword_double(&context,
02292 sel->num_atoms,
02293 tmp_data, sel->on);
02294 delete[] tmp_data;
02295
02296 } else if (atomSelParser->fctns.data(fctn)->returns_a == SymbolTableElement::IS_INT) {
02297 int *tmp_data = new int[sel->num_atoms];
02298 int j=0;
02299 for (int i=sel->firstsel; i<=sel->lastsel; i++) {
02300 if (sel->on[i])
02301 tmp_data[i] = clusternum[j++];
02302 }
02303 atomSelParser->fctns.data(fctn)->set_keyword_int(&context,
02304 sel->num_atoms,
02305 tmp_data, sel->on);
02306 delete[] tmp_data;
02307 } else {
02308 Tcl_AppendResult(interp, "measure clustsize: storenum field must accept numbers", NULL);
02309 return TCL_ERROR;
02310 }
02311 } else {
02312 Tcl_AppendResult(interp, "measure clustsize: invalid field name for storenum", NULL);
02313 return TCL_ERROR;
02314 }
02315 }
02316
02317
02318 if (storesize) {
02319 int fctn = atomSelParser->find_attribute(storesize);
02320 if (fctn >= 0) {
02321 if (atomSelParser->fctns.data(fctn)->returns_a == SymbolTableElement::IS_FLOAT) {
02322 double *tmp_data = new double[sel->num_atoms];
02323 int j=0;
02324 for (int i=sel->firstsel; i<=sel->lastsel; i++) {
02325 if (sel->on[i])
02326 tmp_data[i] = (double) clustersize[j++];
02327 }
02328 atomSelParser->fctns.data(fctn)->set_keyword_double(&context,
02329 sel->num_atoms,
02330 tmp_data, sel->on);
02331 delete[] tmp_data;
02332
02333 } else if (atomSelParser->fctns.data(fctn)->returns_a == SymbolTableElement::IS_INT) {
02334 int *tmp_data = new int[sel->num_atoms];
02335 int j=0;
02336 for (int i=sel->firstsel; i<=sel->lastsel; i++) {
02337 if (sel->on[i])
02338 tmp_data[i] = clustersize[j++];
02339 }
02340 atomSelParser->fctns.data(fctn)->set_keyword_int(&context,
02341 sel->num_atoms,
02342 tmp_data, sel->on);
02343 delete[] tmp_data;
02344 } else {
02345 Tcl_AppendResult(interp, "measure clustsize: storenum field must accept numbers", NULL);
02346 return TCL_ERROR;
02347 }
02348 } else {
02349 Tcl_AppendResult(interp, "measure clustsize: invalid field name for storesize", NULL);
02350 return TCL_ERROR;
02351 }
02352 }
02353 } else {
02354
02355
02356 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
02357
02358 Tcl_Obj *tcl_ilist = Tcl_NewListObj(0, NULL);
02359 Tcl_Obj *tcl_clist = Tcl_NewListObj(0, NULL);
02360 Tcl_Obj *tcl_nlist = Tcl_NewListObj(0, NULL);
02361 for (i=0; i<num_selected; i++) {
02362 Tcl_ListObjAppendElement(interp, tcl_ilist, Tcl_NewIntObj(clusteridx[i]));
02363 Tcl_ListObjAppendElement(interp, tcl_clist, Tcl_NewIntObj(clustersize[i]));
02364 Tcl_ListObjAppendElement(interp, tcl_nlist, Tcl_NewIntObj(clusternum[i]));
02365 }
02366 Tcl_ListObjAppendElement(interp, tcl_result, tcl_ilist);
02367 Tcl_ListObjAppendElement(interp, tcl_result, tcl_clist);
02368 Tcl_ListObjAppendElement(interp, tcl_result, tcl_nlist);
02369 Tcl_SetObjResult(interp, tcl_result);
02370 }
02371
02372 delete[] clustersize;
02373 delete[] clusternum;
02374 delete[] clusteridx;
02375
02376 return TCL_OK;
02377 }
02378
02379 static int vmd_measure_hbonds(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
02380
02381
02382 if (argc != 4 && argc != 5) {
02383 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<cutoff> <angle> <selection1> [<selection2>]");
02384 return TCL_ERROR;
02385 }
02386 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[3],NULL));
02387 if (!sel1) {
02388 Tcl_AppendResult(interp, "measure hbonds: invalid first atom selection", NULL);
02389 return TCL_ERROR;
02390 }
02391
02392 AtomSel *sel2 = NULL;
02393 if (argc == 5) {
02394 sel2 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[4],NULL));
02395 if (!sel2) {
02396 Tcl_AppendResult(interp, "measure hbonds: invalid second atom selection", NULL);
02397 return TCL_ERROR;
02398 }
02399 }
02400 if (sel2 && sel2->molid() != sel1->molid()) {
02401 Tcl_AppendResult(interp, "measure hbonds: error, atom selections must come from same molecule.", NULL);
02402 return TCL_ERROR;
02403 }
02404 double cutoff;
02405 if (Tcl_GetDoubleFromObj(interp, objv[1], &cutoff) != TCL_OK)
02406 return TCL_ERROR;
02407
02408 double maxangle;
02409 if (Tcl_GetDoubleFromObj(interp, objv[2], &maxangle) != TCL_OK)
02410 return TCL_ERROR;
02411
02412 const float *pos = sel1->coordinates(app->moleculeList);
02413 if (!pos) {
02414 Tcl_AppendResult(interp, "measure bondsearch: error, molecule contains no coordinates", NULL);
02415 return TCL_ERROR;
02416 }
02417
02418
02419
02420
02421
02422
02423
02424
02425
02426
02427
02428
02429
02430
02431 Molecule *mol = app->moleculeList->mol_from_id(sel1->molid());
02432
02433 int *donlist, *hydlist, *acclist;
02434 int maxsize = 2 * sel1->num_atoms;
02435 donlist = new int[maxsize];
02436 hydlist = new int[maxsize];
02437 acclist = new int[maxsize];
02438 int rc = measure_hbonds(mol, sel1, sel2, cutoff, maxangle, donlist, hydlist, acclist, maxsize);
02439 if (rc > maxsize) {
02440 delete [] donlist;
02441 delete [] hydlist;
02442 delete [] acclist;
02443 maxsize = rc;
02444 donlist = new int[maxsize];
02445 hydlist = new int[maxsize];
02446 acclist = new int[maxsize];
02447 rc = measure_hbonds(mol, sel1, sel2, cutoff, maxangle, donlist, hydlist, acclist, maxsize);
02448 }
02449 if (rc < 0) {
02450 Tcl_AppendResult(interp, "measure hbonds: internal error to measure_hbonds", NULL);
02451 return TCL_ERROR;
02452 }
02453
02454 Tcl_Obj *newdonlist = Tcl_NewListObj(0, NULL);
02455 Tcl_Obj *newhydlist = Tcl_NewListObj(0, NULL);
02456 Tcl_Obj *newacclist = Tcl_NewListObj(0, NULL);
02457 for (int k = 0; k < rc; k++) {
02458 Tcl_ListObjAppendElement(interp, newdonlist, Tcl_NewIntObj(donlist[k]));
02459 Tcl_ListObjAppendElement(interp, newhydlist, Tcl_NewIntObj(hydlist[k]));
02460 Tcl_ListObjAppendElement(interp, newacclist, Tcl_NewIntObj(acclist[k]));
02461 }
02462 delete [] donlist;
02463 delete [] hydlist;
02464 delete [] acclist;
02465 Tcl_Obj *result = Tcl_NewListObj(0, NULL);
02466 Tcl_ListObjAppendElement(interp, result, newdonlist);
02467 Tcl_ListObjAppendElement(interp, result, newacclist);
02468 Tcl_ListObjAppendElement(interp, result, newhydlist);
02469 Tcl_SetObjResult(interp, result);
02470 return TCL_OK;
02471 }
02472
02473
02474 static int vmd_measure_sasa(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
02475
02476 int i;
02477
02478 if (argc < 3) {
02479 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<srad> <sel> [-points <varname>] [-restrict <restrictedsel>] [-samples <numsamples>]");
02480 return TCL_ERROR;
02481 }
02482
02483 Tcl_Obj *ptsvar = NULL;
02484 AtomSel *restrictsel = NULL;
02485 int nsamples = -1;
02486 int *sampleptr = NULL;
02487 for (i=3; i<argc-1; i+=2) {
02488 const char *opt = Tcl_GetStringFromObj(objv[i], NULL);
02489 if (!strcmp(opt, "-points")) {
02490 ptsvar = objv[i+1];
02491 } else if (!strcmp(opt, "-restrict")) {
02492 restrictsel = tcl_commands_get_sel(interp,
02493 Tcl_GetStringFromObj(objv[i+1], NULL));
02494 if (!restrictsel) {
02495 Tcl_AppendResult(interp, "measure sasa: invalid restrict atom selection", NULL);
02496 return TCL_ERROR;
02497 }
02498 } else if (!strcmp(opt, "-samples")) {
02499 if (Tcl_GetIntFromObj(interp, objv[i+1], &nsamples) != TCL_OK)
02500 return TCL_ERROR;
02501 sampleptr = &nsamples;
02502 } else {
02503 Tcl_AppendResult(interp, "measure sasa: unknown option '", opt, "'",
02504 NULL);
02505 return TCL_ERROR;
02506 }
02507 }
02508
02509 double srad;
02510 if (Tcl_GetDoubleFromObj(interp, objv[1], &srad) != TCL_OK)
02511 return TCL_ERROR;
02512 AtomSel *sel1 = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[2],NULL));
02513 if (!sel1) {
02514 Tcl_AppendResult(interp, "measure sasa: invalid first atom selection", NULL);
02515 return TCL_ERROR;
02516 }
02517
02518 const float *pos = sel1->coordinates(app->moleculeList);
02519 if (!pos) {
02520 Tcl_AppendResult(interp, "measure sasa: error, molecule contains no coordinates", NULL);
02521 return TCL_ERROR;
02522 }
02523 Molecule *mol = app->moleculeList->mol_from_id(sel1->molid());
02524 const float *radius = mol->extraflt.data("radius");
02525
02526 ResizeArray<float> sasapts;
02527 float sasa = 0;
02528 int rc = measure_sasa(sel1, pos, radius, (float) srad, &sasa, &sasapts,
02529 restrictsel, sampleptr);
02530 if (rc < 0) {
02531 Tcl_AppendResult(interp, "measure: sasa: ", measure_error(rc), NULL);
02532 return TCL_ERROR;
02533 }
02534 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(sasa));
02535 if (ptsvar) {
02536
02537 Tcl_Obj *listobj = Tcl_NewListObj(0, NULL);
02538 i=0;
02539 while (i<sasapts.num()) {
02540 Tcl_Obj *elem = Tcl_NewListObj(0, NULL);
02541 Tcl_ListObjAppendElement(interp, elem, Tcl_NewDoubleObj(sasapts[i++]));
02542 Tcl_ListObjAppendElement(interp, elem, Tcl_NewDoubleObj(sasapts[i++]));
02543 Tcl_ListObjAppendElement(interp, elem, Tcl_NewDoubleObj(sasapts[i++]));
02544 Tcl_ListObjAppendElement(interp, listobj, elem);
02545 }
02546 Tcl_ObjSetVar2(interp, ptsvar, NULL, listobj, 0);
02547 }
02548 return TCL_OK;
02549 }
02550
02551
02552 #if 1
02553
02554 static int vmd_measure_sasalist(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
02555
02556 int i;
02557
02558 if (argc < 3) {
02559 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<srad> <sel list> [-samples <numsamples>]");
02560 return TCL_ERROR;
02561 }
02562
02563
02564 int nsamples = -1;
02565 int *sampleptr = NULL;
02566 for (i=3; i<argc-1; i+=2) {
02567 const char *opt = Tcl_GetStringFromObj(objv[i], NULL);
02568
02569 if (!strcmp(opt, "-samples")) {
02570 if (Tcl_GetIntFromObj(interp, objv[i+1], &nsamples) != TCL_OK)
02571 return TCL_ERROR;
02572 sampleptr = &nsamples;
02573 } else {
02574 Tcl_AppendResult(interp, "measure sasa: unknown option '", opt, "'", NULL);
02575 return TCL_ERROR;
02576 }
02577 }
02578
02579 double srad;
02580 if (Tcl_GetDoubleFromObj(interp, objv[1], &srad) != TCL_OK)
02581 return TCL_ERROR;
02582
02583 int numsels;
02584 Tcl_Obj **sel_list;
02585 if (Tcl_ListObjGetElements(interp, objv[2], &numsels, &sel_list) != TCL_OK) {
02586 Tcl_AppendResult(interp, "measure sasalist: bad selection list", NULL);
02587 return TCL_ERROR;
02588 }
02589
02590 #if 0
02591 printf("measure sasalist: numsels %d\n", numsels);
02592 #endif
02593
02594 AtomSel **asels = (AtomSel **) calloc(1, numsels * sizeof(AtomSel *));
02595 float *sasalist = (float *) calloc(1, numsels * sizeof(float));
02596
02597 int s;
02598 for (s=0; s<numsels; s++) {
02599 asels[s] = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(sel_list[s], NULL));
02600 if (!asels[s]) {
02601 printf("measure sasalist: invalid selection %d\n", s);
02602 Tcl_AppendResult(interp, "measure sasalist: invalid atom selection list element", NULL);
02603 return TCL_ERROR;
02604 }
02605 }
02606
02607 int rc = measure_sasalist(app->moleculeList, (const AtomSel **) asels,
02608 numsels, (float) srad, sasalist, sampleptr);
02609 free(asels);
02610 if (rc < 0) {
02611 Tcl_AppendResult(interp, "measure: sasalist: ", measure_error(rc), NULL);
02612 return TCL_ERROR;
02613 }
02614
02615
02616 Tcl_Obj *listobj = Tcl_NewListObj(0, NULL);
02617 for (i=0; i<numsels; i++) {
02618 Tcl_ListObjAppendElement(interp, listobj, Tcl_NewDoubleObj(sasalist[i]));
02619 }
02620 Tcl_SetObjResult(interp, listobj);
02621 free(sasalist);
02622
02623 return TCL_OK;
02624 }
02625
02626 #endif
02627
02628
02629
02630
02631
02632 static int vmd_measure_energy(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
02633
02634 if (argc<3) {
02635 Tcl_WrongNumArgs(interp, 2, objv-1,
02636 (char *) "bond|angle|dihed|imprp|vdw|elec {{<atomid1> ?<molid1>?} {<atomid2> ?<molid2>?}} ?molid <default molid>? [?frame <frame|all>? | ?first <first>? ?last <last>?]");
02637 return TCL_ERROR;
02638 }
02639
02640 int geomtype, reqatoms;
02641 char *geomname = Tcl_GetStringFromObj(objv[1],NULL);
02642 if (!strncmp(geomname, "bond", 4)) {
02643 reqatoms = 2; geomtype = MEASURE_BOND;
02644 } else if (!strncmp(geomname, "angl", 4)) {
02645 reqatoms = 3; geomtype = MEASURE_ANGLE;
02646 } else if (!strncmp(geomname, "dihe", 4)) {
02647 reqatoms = 4; geomtype = MEASURE_DIHED;
02648 } else if (!strncmp(geomname, "impr", 4)) {
02649 reqatoms = 4; geomtype = MEASURE_IMPRP;
02650 } else if (!strncmp(geomname, "vdw", 3)) {
02651 reqatoms = 2; geomtype = MEASURE_VDW;
02652 } else if (!strncmp(geomname, "elec", 4)) {
02653 reqatoms = 2; geomtype = MEASURE_ELECT;
02654 } else {
02655 Tcl_AppendResult(interp, " measure energy: bad syntax (must specify bond|angle|dihed|imprp|vdw|elec)", NULL);
02656 return TCL_ERROR;
02657 }
02658
02659 int molid[4];
02660 int atmid[4];
02661 int defmolid = -1;
02662 bool allframes = false;
02663 char errstring[200];
02664
02665
02666 int numatms;
02667 Tcl_Obj **data;
02668 if (Tcl_ListObjGetElements(interp, objv[2], &numatms, &data) != TCL_OK) {
02669 Tcl_AppendResult(interp, " measure energy: bad syntax", NULL);
02670 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);
02671 return TCL_ERROR;
02672 }
02673
02674 if (numatms!=reqatoms) {
02675 sprintf(errstring, " measure energy %s: must specify exactly %i atoms in list", geomname, reqatoms);
02676 Tcl_AppendResult(interp, errstring, NULL);
02677 return TCL_ERROR;
02678 }
02679
02680 int first=-1, last=-1, frame=-1;
02681 double params[6];
02682 memset(params, 0, 6L*sizeof(double));
02683
02684 if (argc>4) {
02685 int i;
02686 for (i=3; i<argc-1; i+=2) {
02687 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
02688 if (!strupncmp(argvcur, "molid", CMDLEN)) {
02689 if (Tcl_GetIntFromObj(interp, objv[i+1], &defmolid) != TCL_OK) {
02690 Tcl_AppendResult(interp, " measure energy: bad molid", NULL);
02691 return TCL_ERROR;
02692 }
02693 } else if (!strupncmp(argvcur, "k", CMDLEN)) {
02694 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params) != TCL_OK) {
02695 Tcl_AppendResult(interp, " measure energy: bad force constant value", NULL);
02696 return TCL_ERROR;
02697 }
02698 } else if (!strupncmp(argvcur, "x0", CMDLEN)) {
02699 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+1) != TCL_OK) {
02700 Tcl_AppendResult(interp, " measure energy: bad equilibrium value", NULL);
02701 return TCL_ERROR;
02702 }
02703 } else if (!strupncmp(argvcur, "kub", CMDLEN)) {
02704 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+2) != TCL_OK) {
02705 Tcl_AppendResult(interp, " measure energy: bad Urey-Bradley force constant value", NULL);
02706 return TCL_ERROR;
02707 }
02708 } else if (!strupncmp(argvcur, "s0", CMDLEN)) {
02709 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+3) != TCL_OK) {
02710 Tcl_AppendResult(interp, " measure energy: bad Urey-Bradley equilibrium distance", NULL);
02711 return TCL_ERROR;
02712 }
02713 } else if (!strupncmp(argvcur, "n", CMDLEN)) {
02714 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+1) != TCL_OK) {
02715 Tcl_AppendResult(interp, " measure energy: bad dihedral periodicity", NULL);
02716 return TCL_ERROR;
02717 }
02718 } else if (!strupncmp(argvcur, "delta", CMDLEN)) {
02719 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+2) != TCL_OK) {
02720 Tcl_AppendResult(interp, " measure energy: bad dihedral phase shift", NULL);
02721 return TCL_ERROR;
02722 }
02723 } else if (!strupncmp(argvcur, "eps1", CMDLEN)) {
02724 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params) != TCL_OK) {
02725 Tcl_AppendResult(interp, " measure energy: bad vdw well depth", NULL);
02726 return TCL_ERROR;
02727 }
02728 } else if (!strupncmp(argvcur, "rmin1", CMDLEN)) {
02729 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+1) != TCL_OK) {
02730 Tcl_AppendResult(interp, " measure energy: bad vdw equilibrium distance", NULL);
02731 return TCL_ERROR;
02732 }
02733 } else if (!strupncmp(argvcur, "eps2", CMDLEN)) {
02734 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+2) != TCL_OK) {
02735 Tcl_AppendResult(interp, " measure energy: bad vdw well depth", NULL);
02736 return TCL_ERROR;
02737 }
02738 } else if (!strupncmp(argvcur, "rmin2", CMDLEN)) {
02739 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+3) != TCL_OK) {
02740 Tcl_AppendResult(interp, " measure energy: bad vdw equilibrium distance", NULL);
02741 return TCL_ERROR;
02742 }
02743 } else if (!strupncmp(argvcur, "q1", CMDLEN)) {
02744 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params) != TCL_OK) {
02745 Tcl_AppendResult(interp, " measure energy: bad charge value", NULL);
02746 return TCL_ERROR;
02747 }
02748 params[2]=1.0;
02749 } else if (!strupncmp(argvcur, "q2", CMDLEN)) {
02750 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+1) != TCL_OK) {
02751 Tcl_AppendResult(interp, " measure energy: bad charge value", NULL);
02752 return TCL_ERROR;
02753 }
02754 params[3]=1.0;
02755 } else if (!strupncmp(argvcur, "cutoff", CMDLEN)) {
02756 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+4) != TCL_OK) {
02757 Tcl_AppendResult(interp, " measure energy: bad electrostatic cutoff value", NULL);
02758 return TCL_ERROR;
02759 }
02760 } else if (!strupncmp(argvcur, "switchdist", CMDLEN)) {
02761 if (Tcl_GetDoubleFromObj(interp, objv[i+1], params+5) != TCL_OK) {
02762 Tcl_AppendResult(interp, " measure energy: bad switching distance value", NULL);
02763 return TCL_ERROR;
02764 }
02765 } else if (!strupncmp(argvcur, "first", CMDLEN)) {
02766 if (Tcl_GetIntFromObj(interp, objv[i+1], &first) != TCL_OK) {
02767 Tcl_AppendResult(interp, " measure energy: bad first frame value", NULL);
02768 return TCL_ERROR;
02769 }
02770 } else if (!strupncmp(argvcur, "last", CMDLEN)) {
02771 if (Tcl_GetIntFromObj(interp, objv[i+1], &last) != TCL_OK) {
02772 Tcl_AppendResult(interp, " measure energy: bad last frame value", NULL);
02773 return TCL_ERROR;
02774 }
02775 } else if (!strupncmp(argvcur, "frame", CMDLEN)) {
02776 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "all")) {
02777 allframes = true;
02778 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &frame) != TCL_OK) {
02779 Tcl_AppendResult(interp, " measure energy: bad frame value", NULL);
02780 return TCL_ERROR;
02781 }
02782 } else {
02783 Tcl_AppendResult(interp, " measure energy: invalid syntax, no such keyword: ", argvcur, NULL);
02784 return TCL_ERROR;
02785 }
02786 }
02787 }
02788
02789 if ((allframes || frame>=0) && (first>=0 || last>=0)) {
02790 Tcl_AppendResult(interp, "measure energy: Ambiguous syntax: You cannot specify a frame AND a frame range (using first or last).", NULL);
02791 Tcl_AppendResult(interp, "\nUsage:\nmeasure bond <molid1>/<atomid1> <molid2>/<atomid2> [?frame <frame|all>? | ?first <first>? ?last <last>?]", NULL);
02792 return TCL_ERROR;
02793 }
02794
02795 if (allframes) first=0;
02796
02797
02798 if (defmolid<0) defmolid = app->molecule_top();
02799
02800
02801 int i,numelem;
02802 Tcl_Obj **atmmol;
02803 for (i=0; i<numatms; i++) {
02804 if (Tcl_ListObjGetElements(interp, data[i], &numelem, &atmmol) != TCL_OK) {
02805 return TCL_ERROR;
02806 }
02807
02808 if (Tcl_GetIntFromObj(interp, atmmol[0], atmid+i) != TCL_OK) {
02809 Tcl_AppendResult(interp, " measure energy: bad atom index", NULL);
02810 return TCL_ERROR;
02811 }
02812
02813 if (numelem==2) {
02814 if (Tcl_GetIntFromObj(interp, atmmol[1], molid+i) != TCL_OK) {
02815 Tcl_AppendResult(interp, " measure energy: bad molid", NULL);
02816 return TCL_ERROR;
02817 }
02818 } else molid[i] = defmolid;
02819 }
02820
02821
02822
02823 ResizeArray<float> gValues(1024);
02824 int ret_val;
02825 ret_val = measure_energy(app->moleculeList, molid, atmid, reqatoms, &gValues, frame, first, last, defmolid, params, geomtype);
02826 if (ret_val<0) {
02827 printf("ERROR\n %s\n", measure_error(ret_val));
02828 Tcl_AppendResult(interp, measure_error(ret_val), NULL);
02829 return TCL_ERROR;
02830 }
02831
02832 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
02833 int numvalues = gValues.num();
02834 for (int count = 0; count < numvalues; count++) {
02835 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(gValues[count]));
02836 }
02837 Tcl_SetObjResult(interp, tcl_result);
02838
02839 return TCL_OK;
02840 }
02841
02842
02843
02844
02845
02846 static int vmd_measure_surface(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
02847 if (argc!=5) {
02848 Tcl_WrongNumArgs(interp, 2, objv-1,
02849 (char *) "<sel> <gridsize> <radius> <depth>");
02850 return TCL_ERROR;
02851 }
02852
02853 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
02854 if (!sel) {
02855 Tcl_AppendResult(interp, "measure surface: no atom selection", NULL);
02856 return TCL_ERROR;
02857 }
02858
02859 const float *framepos = sel->coordinates(app->moleculeList);
02860 if (!framepos) return TCL_ERROR;
02861
02862 double gridsz;
02863 if (Tcl_GetDoubleFromObj(interp, objv[2], &gridsz) != TCL_OK)
02864 return TCL_ERROR;
02865
02866 double radius;
02867 if (Tcl_GetDoubleFromObj(interp, objv[3], &radius) != TCL_OK)
02868 return TCL_ERROR;
02869
02870 double depth;
02871 if (Tcl_GetDoubleFromObj(interp, objv[4], &depth) != TCL_OK)
02872 return TCL_ERROR;
02873
02874 int *surface;
02875 int n_surf;
02876
02877 int ret_val = measure_surface(sel, app->moleculeList, framepos,
02878 gridsz, radius, depth, &surface, &n_surf);
02879 if (ret_val < 0) {
02880 Tcl_AppendResult(interp, "measure surface: ", measure_error(ret_val));
02881 return TCL_ERROR;
02882 }
02883
02884 Tcl_Obj *surf_list = Tcl_NewListObj(0, NULL);
02885
02886 int i;
02887 for(i=0; i < n_surf; i++) {
02888 Tcl_ListObjAppendElement(interp, surf_list, Tcl_NewIntObj(surface[i]));
02889 }
02890 Tcl_SetObjResult(interp, surf_list);
02891 delete [] surface;
02892
02893 return TCL_OK;
02894 }
02895
02896
02897
02898
02899
02900 static int vmd_measure_pbc2onc_transform(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
02901 if (argc < 2) {
02902 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<center> [molid <default>] [frame <frame|last>]");
02903 return TCL_ERROR;
02904 }
02905
02906
02907 int ndim;
02908 Tcl_Obj **centerObj;
02909 if (Tcl_ListObjGetElements(interp, objv[1], &ndim, ¢erObj) != TCL_OK) {
02910 Tcl_AppendResult(interp, " measure pbc2onc: bad syntax", NULL);
02911 Tcl_AppendResult(interp, " Usage: measure pbc2onc <center> [molid <default>] [frame <frame|last>]", NULL);
02912 return TCL_ERROR;
02913 }
02914
02915 if (ndim!=3) {
02916 Tcl_AppendResult(interp, " measure pbc2onc: need three numbers for a vector", NULL);
02917 return TCL_ERROR;
02918 }
02919
02920 int i;
02921 double tmp;
02922 float center[3];
02923 for (i=0; i<3; i++) {
02924 if (Tcl_GetDoubleFromObj(interp, centerObj[i], &tmp) != TCL_OK) {
02925 Tcl_AppendResult(interp, " measure pbc2onc: non-numeric in center", NULL);
02926 return TCL_ERROR;
02927 }
02928 center[i] = (float)tmp;
02929 }
02930
02931 int molid = app->molecule_top();
02932 int frame = -2;
02933 if (argc>3) {
02934 for (i=2; i<argc; i+=2) {
02935 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
02936 if (!strupncmp(argvcur, "molid", CMDLEN)) {
02937
02938 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "top")) {
02939
02940 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &molid) != TCL_OK) {
02941 Tcl_AppendResult(interp, " measure pbc2onc: bad molid", NULL);
02942 return TCL_ERROR;
02943 }
02944 } else if (!strupncmp(argvcur, "frame", CMDLEN)) {
02945 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "last")) {
02946 frame=-1;
02947 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &frame) != TCL_OK) {
02948 Tcl_AppendResult(interp, " measure pbc2onc: bad frame value", NULL);
02949 return TCL_ERROR;
02950 }
02951 } else {
02952 Tcl_AppendResult(interp, " measure pbc2onc: invalid syntax, no such keyword: ", argvcur, NULL);
02953 return TCL_ERROR;
02954 }
02955 }
02956 }
02957
02958
02959 Matrix4 transform;
02960 int ret_val = measure_pbc2onc(app->moleculeList, molid, frame, center, transform);
02961 if (ret_val < 0) {
02962 Tcl_AppendResult(interp, "measure pbc2onc: ", measure_error(ret_val), NULL);
02963 return TCL_ERROR;
02964 }
02965
02966 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
02967 for (i=0; i<4; i++) {
02968 Tcl_Obj *rowListObj = Tcl_NewListObj(0, NULL);
02969 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(transform.mat[i+0]));
02970 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(transform.mat[i+4]));
02971 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(transform.mat[i+8]));
02972 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(transform.mat[i+12]));
02973 Tcl_ListObjAppendElement(interp, tcl_result, rowListObj);
02974 }
02975 Tcl_SetObjResult(interp, tcl_result);
02976
02977 return TCL_OK;
02978 }
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010 static int vmd_measure_pbc_neighbors(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
03011 if (argc < 3) {
03012 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<center> <cutoff> ?sel <selection>? ?align <matrix>? ?molid <default>? ?frame <frame|last>? ?boundingbox PBC|{<mincoord> <maxcoord>}?");
03013 return TCL_ERROR;
03014 }
03015
03016
03017 int ndim;
03018 Tcl_Obj **centerObj;
03019 if (Tcl_ListObjGetElements(interp, objv[1], &ndim, ¢erObj) != TCL_OK) {
03020 Tcl_AppendResult(interp, " measure pbcneighbors: bad syntax", NULL);
03021 Tcl_AppendResult(interp, " Usage: measure pbcneighbors <center> <cutoff> [<sel <sel>] [align <matrix>] [molid <default>] [frame <frame|last>] [boundingbox <PBC|{<mincoord> <maxcoord>}>]", NULL);
03022 return TCL_ERROR;
03023 }
03024
03025 if (ndim!=3) {
03026 Tcl_AppendResult(interp, " measure pbcneighbors: need three numbers for a vector", NULL);
03027 return TCL_ERROR;
03028 }
03029
03030 int i;
03031 double tmp;
03032 float center[3];
03033 for (i=0; i<3; i++) {
03034 if (Tcl_GetDoubleFromObj(interp, centerObj[i], &tmp) != TCL_OK) {
03035 Tcl_AppendResult(interp, " measure pbcneighbors: non-numeric in center", NULL);
03036 return TCL_ERROR;
03037 }
03038 center[i] = float(tmp);
03039 }
03040
03041
03042 Tcl_Obj **cutoffObj;
03043 if (Tcl_ListObjGetElements(interp, objv[2], &ndim, &cutoffObj) != TCL_OK) {
03044 Tcl_AppendResult(interp, " measure pbcneighbors: bad syntax", NULL);
03045 Tcl_AppendResult(interp, " Usage: measure pbcneighbors <center> <cutoff> [<sel <sel>] [align <matrix>] [molid <default>] [frame <frame|last>] [boundingbox <PBC|{<mincoord> <maxcoord>}>]", NULL);
03046 return TCL_ERROR;
03047 }
03048
03049 if (ndim!=3 && ndim!=1) {
03050 Tcl_AppendResult(interp, " measure pbcneighbors: need either one or three numbers for cutoff", NULL);
03051 return TCL_ERROR;
03052 }
03053
03054 float cutoff[3];
03055 for (i=0; i<ndim; i++) {
03056 if (Tcl_GetDoubleFromObj(interp, cutoffObj[i], &tmp) != TCL_OK) {
03057 Tcl_AppendResult(interp, " measure pbcneighbors: non-numeric in cutoff", NULL);
03058 return TCL_ERROR;
03059 }
03060 cutoff[i] = float(tmp);
03061 }
03062
03063 if (ndim==1) { cutoff[2] = cutoff[1] = cutoff[0]; }
03064
03065 bool molidprovided=0;
03066 float *boxminmax=NULL;
03067 int molid = app->molecule_top();
03068 int frame = -2;
03069 AtomSel *sel = NULL;
03070 Matrix4 alignment;
03071 if (argc>4) {
03072 for (i=3; i<argc; i+=2) {
03073 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
03074 if (!strupncmp(argvcur, "sel", CMDLEN)) {
03075
03076 sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[i+1],NULL));
03077 if (!sel) {
03078 Tcl_AppendResult(interp, "measure pbcneighbors: invalid atom selection", NULL);
03079 return TCL_ERROR;
03080 }
03081 if (!app->molecule_valid_id(sel->molid())) {
03082 Tcl_AppendResult(interp, "measure pbcneighbors: ",
03083 measure_error(MEASURE_ERR_NOMOLECULE), NULL);
03084 return TCL_ERROR;
03085 }
03086 if (!sel->selected) {
03087 Tcl_AppendResult(interp, "measure pbcneighbors: selection contains no atoms.", NULL);
03088 return TCL_ERROR;
03089 }
03090 } else if (!strupncmp(argvcur, "molid", CMDLEN)) {
03091 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "top")) {
03092
03093 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &molid) != TCL_OK) {
03094 Tcl_AppendResult(interp, " measure pbcneighbors: bad molid", NULL);
03095 return TCL_ERROR;
03096 }
03097 molidprovided = 1;
03098 } else if (!strupncmp(argvcur, "frame", CMDLEN)) {
03099 if (!strupcmp(Tcl_GetStringFromObj(objv[i+1],NULL), "last")) {
03100 frame=-1;
03101 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &frame) != TCL_OK) {
03102 Tcl_AppendResult(interp, " measure pbcneighbors: bad frame value", NULL);
03103 return TCL_ERROR;
03104 }
03105 } else if (!strupncmp(argvcur, "align", CMDLEN)) {
03106
03107 if (tcl_get_matrix("measure pbcneighbors: ", interp, objv[i+1], alignment.mat) != TCL_OK) {
03108 return TCL_ERROR;
03109 }
03110 } else if (!strupncmp(argvcur, "boundingbox", CMDLEN)) {
03111
03112
03113 char *argv2 = Tcl_GetStringFromObj(objv[i+1],NULL);
03114 if (!strupncmp(argv2, "on", CMDLEN) || !strupncmp(argv2, "pbc", CMDLEN)) {
03115 boxminmax = new float[6];
03116 compute_pbcminmax(app->moleculeList, molid, frame, center, &alignment,
03117 boxminmax, boxminmax+3);
03118 } else {
03119
03120 int j, k, ncoor;
03121 Tcl_Obj **boxListObj;
03122 if (Tcl_ListObjGetElements(interp, objv[i+1], &ncoor, &boxListObj) != TCL_OK) {
03123 Tcl_AppendResult(interp, " measure pbcneighbors: invalid bounding box parameter", NULL);
03124 return TCL_ERROR;
03125 }
03126 if (ncoor!=2) {
03127 Tcl_AppendResult(interp, " measure pbcneighbors: need 2 points for bounding box", NULL);
03128 return TCL_ERROR;
03129 }
03130 int ndim = 0;
03131 double tmp;
03132 Tcl_Obj **boxObj;
03133 boxminmax = new float[6];
03134 for (j=0; j<2; j++) {
03135 if (Tcl_ListObjGetElements(interp, boxListObj[j], &ndim, &boxObj) != TCL_OK) {
03136 Tcl_AppendResult(interp, " measure pbcneighbors: bad syntax in boundingbox", NULL);
03137 return TCL_ERROR;
03138 }
03139
03140 for (k=0; k<3; k++) {
03141 if (Tcl_GetDoubleFromObj(interp, boxObj[k], &tmp) != TCL_OK) {
03142 Tcl_AppendResult(interp, " measure pbcneighbors: non-numeric in boundingbox", NULL);
03143 return TCL_ERROR;
03144 }
03145 boxminmax[3L*j+k] = (float)tmp;
03146 }
03147 }
03148 }
03149
03150 } else {
03151 Tcl_AppendResult(interp, " measure pbcneighbors: invalid syntax, no such keyword: ", argvcur, NULL);
03152 return TCL_ERROR;
03153 }
03154 }
03155 }
03156
03157
03158
03159 if (sel && !molidprovided) {
03160 molid = sel->molid();
03161 }
03162
03163 ResizeArray<float> extcoord_array;
03164 ResizeArray<int> indexmap_array;
03165
03166 int ret_val = measure_pbc_neighbors(app->moleculeList, sel, molid, frame, &alignment, center, cutoff, boxminmax, &extcoord_array, &indexmap_array);
03167 delete [] boxminmax;
03168
03169 if (ret_val < 0) {
03170 Tcl_AppendResult(interp, "measure pbcneighbors: ", measure_error(ret_val), NULL);
03171 return TCL_ERROR;
03172 }
03173 printf("measure pbcneighbors: %ld neighbor atoms found\n",
03174 long(indexmap_array.num()));
03175
03176 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
03177 Tcl_Obj *coorListObj = Tcl_NewListObj(0, NULL);
03178 Tcl_Obj *indexListObj = Tcl_NewListObj(0, NULL);
03179 for (i=0; i<indexmap_array.num(); i++) {
03180 Tcl_Obj *rowListObj = Tcl_NewListObj(0, NULL);
03181 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(extcoord_array[3L*i]));
03182 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(extcoord_array[3L*i+1]));
03183 Tcl_ListObjAppendElement(interp, rowListObj, Tcl_NewDoubleObj(extcoord_array[3L*i+2]));
03184 Tcl_ListObjAppendElement(interp, coorListObj, rowListObj);
03185 Tcl_ListObjAppendElement(interp, indexListObj, Tcl_NewIntObj(indexmap_array[i]));
03186 }
03187 Tcl_ListObjAppendElement(interp, tcl_result, coorListObj);
03188 Tcl_ListObjAppendElement(interp, tcl_result, indexListObj);
03189 Tcl_SetObjResult(interp, tcl_result);
03190
03191 return TCL_OK;
03192 }
03193
03194
03195
03196
03197
03198
03199
03200
03201 static int vmd_measure_inertia(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
03202 bool moments = FALSE;
03203 bool eigenvals = FALSE;
03204 if (argc < 2 || argc > 4) {
03205 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<selection> [moments] [eigenvals]");
03206 return TCL_ERROR;
03207 }
03208 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
03209 if (!sel) {
03210 Tcl_AppendResult(interp, "measure inertia: no atom selection", NULL);
03211 return TCL_ERROR;
03212 }
03213
03214 if (!app->molecule_valid_id(sel->molid())) {
03215 Tcl_AppendResult(interp, "measure inertia: ",
03216 measure_error(MEASURE_ERR_NOMOLECULE), NULL);
03217 return TCL_ERROR;
03218 }
03219
03220 if (argc>2) {
03221 int i;
03222 for (i=2; i<argc; i++) {
03223 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
03224
03225 if (argvcur[0]=='-') argvcur++;
03226
03227 if (!strupncmp(argvcur, "moments", CMDLEN)) {
03228 moments = TRUE;
03229 }
03230 else if (!strupncmp(argvcur, "eigenvals", CMDLEN)) {
03231 eigenvals = TRUE;
03232 }
03233 else {
03234 Tcl_AppendResult(interp, " measure inertia: unrecognized option\n", NULL);
03235 Tcl_AppendResult(interp, " Usage: measure inertia <selection> [moments] [eigenvals]", NULL);
03236 return TCL_ERROR;
03237 }
03238 }
03239 }
03240
03241 float priaxes[3][3];
03242 float itensor[4][4];
03243 float evalue[3], rcom[3];
03244 int ret_val = measure_inertia(sel, app->moleculeList, NULL, rcom, priaxes, itensor, evalue);
03245 if (ret_val < 0) {
03246 Tcl_AppendResult(interp, "measure inertia: ", measure_error(ret_val), NULL);
03247 return TCL_ERROR;
03248 }
03249
03250
03251 int i;
03252 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
03253
03254 Tcl_Obj *rcomObj = Tcl_NewListObj(0, NULL);
03255 Tcl_ListObjAppendElement(interp, rcomObj, Tcl_NewDoubleObj(rcom[0]));
03256 Tcl_ListObjAppendElement(interp, rcomObj, Tcl_NewDoubleObj(rcom[1]));
03257 Tcl_ListObjAppendElement(interp, rcomObj, Tcl_NewDoubleObj(rcom[2]));
03258 Tcl_ListObjAppendElement(interp, tcl_result, rcomObj);
03259
03260 Tcl_Obj *axesListObj = Tcl_NewListObj(0, NULL);
03261 for (i=0; i<3; i++) {
03262 Tcl_Obj *axesObj = Tcl_NewListObj(0, NULL);
03263 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(priaxes[i][0]));
03264 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(priaxes[i][1]));
03265 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(priaxes[i][2]));
03266 Tcl_ListObjAppendElement(interp, axesListObj, axesObj);
03267 }
03268 Tcl_ListObjAppendElement(interp, tcl_result, axesListObj);
03269
03270 if (moments) {
03271 Tcl_Obj *momListObj = Tcl_NewListObj(0, NULL);
03272 for (i=0; i<3; i++) {
03273 Tcl_Obj *momObj = Tcl_NewListObj(0, NULL);
03274 Tcl_ListObjAppendElement(interp, momObj, Tcl_NewDoubleObj(itensor[i][0]));
03275 Tcl_ListObjAppendElement(interp, momObj, Tcl_NewDoubleObj(itensor[i][1]));
03276 Tcl_ListObjAppendElement(interp, momObj, Tcl_NewDoubleObj(itensor[i][2]));
03277 Tcl_ListObjAppendElement(interp, momListObj, momObj);
03278 }
03279 Tcl_ListObjAppendElement(interp, tcl_result, momListObj);
03280 }
03281
03282 if (eigenvals) {
03283 Tcl_Obj *eigvListObj = Tcl_NewListObj(0, NULL);
03284 Tcl_ListObjAppendElement(interp, eigvListObj, Tcl_NewDoubleObj(evalue[0]));
03285 Tcl_ListObjAppendElement(interp, eigvListObj, Tcl_NewDoubleObj(evalue[1]));
03286 Tcl_ListObjAppendElement(interp, eigvListObj, Tcl_NewDoubleObj(evalue[2]));
03287 Tcl_ListObjAppendElement(interp, tcl_result, eigvListObj);
03288 }
03289 Tcl_SetObjResult(interp, tcl_result);
03290
03291 return TCL_OK;
03292 }
03293
03294
03295
03296
03297
03298
03299
03300
03301
03302
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317
03318
03319
03320
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333
03334
03335
03336
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
03363
03364
03365
03366
03367
03368
03369
03370
03371
03372
03373
03374
03375
03376
03377
03378
03379
03380
03381
03382
03383
03384 static int vmd_measure_symmetry(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
03385 if (argc<2) {
03386 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> [element [<vector>]] [-tol <value>] [-nobonds] [-verbose <level>]");
03387 return TCL_ERROR;
03388 }
03389 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
03390 if (!sel) {
03391 Tcl_AppendResult(interp, "measure symmetry: no atom selection", NULL);
03392 return TCL_ERROR;
03393 }
03394 if (!app->molecule_valid_id(sel->molid())) {
03395 Tcl_AppendResult(interp, "measure symmetry: ",
03396 measure_error(MEASURE_ERR_NOMOLECULE), NULL);
03397 return TCL_ERROR;
03398 }
03399
03400 double sigma = 0.1;
03401 float axis[3];
03402 int checkelement = 0;
03403 int checkbonds = 1;
03404 int order = 0;
03405 int verbose = 1;
03406 int impose = 0;
03407 int imposeinvers = 0;
03408 int numimposeplan = 0;
03409 int numimposeaxes = 0;
03410 int numimposerref = 0;
03411 float *imposeplan = NULL;
03412 float *imposeaxes = NULL;
03413 float *imposerref = NULL;
03414 int *imposeaxesord = NULL;
03415 int *imposerreford = NULL;
03416 AtomSel *idealsel = NULL;
03417
03418 if (argc>2) {
03419 int bailout = 0;
03420 int i;
03421 for (i=2; (i<argc && !bailout); i++) {
03422 char *argvcur = Tcl_GetStringFromObj(objv[i],NULL);
03423
03424 if (argvcur[0]=='-') argvcur++;
03425
03426 if (!strupncmp(argvcur, "tol", CMDLEN)) {
03427 if (Tcl_GetDoubleFromObj(interp, objv[i+1], &sigma) != TCL_OK) {
03428 Tcl_AppendResult(interp, " measure symmetry: bad tolerance value", NULL);
03429 bailout = 1; continue;
03430 }
03431 i++;
03432 }
03433 else if (!strupncmp(argvcur, "verbose", CMDLEN)) {
03434 if (Tcl_GetIntFromObj(interp, objv[i+1], &verbose) != TCL_OK) {
03435 Tcl_AppendResult(interp, " measure symmetry: bad verbosity level value", NULL);
03436 bailout = 1; continue;
03437 }
03438 i++;
03439 }
03440 else if (!strupncmp(argvcur, "nobonds", CMDLEN)) {
03441 checkbonds = 0;
03442 }
03443 else if (!strupcmp(argvcur, "I")) {
03444 checkelement = 1;
03445 }
03446 else if (!strupncmp(argvcur, "plane", CMDLEN)) {
03447 if (tcl_get_vector(Tcl_GetStringFromObj(objv[i+1],NULL), axis, interp)!=TCL_OK) {
03448 bailout = 1; continue;
03449 }
03450 checkelement = 2;
03451 i++;
03452 }
03453 else if (!strupncmp(argvcur, "C", 1) || !strupncmp(argvcur, "S", 1)) {
03454 char *begptr = argvcur+1;
03455 char *endptr;
03456 order = strtol(begptr, &endptr, 10);
03457 if (endptr==begptr || *endptr!='\0') {
03458 Tcl_AppendResult(interp, " measure symmetry: bad symmetry element format (must be I, C*, S*, plane, where * is the order). ", NULL);
03459 bailout = 1; continue;
03460 }
03461
03462 if (tcl_get_vector(Tcl_GetStringFromObj(objv[i+1],NULL), axis, interp)!=TCL_OK) {
03463 bailout = 1; continue;
03464 }
03465
03466 if (!strupncmp(argvcur, "C", 1)) checkelement = 3;
03467 if (!strupncmp(argvcur, "S", 1)) checkelement = 4;
03468 i++;
03469 }
03470 else if (!strupncmp(argvcur, "idealsel", CMDLEN)) {
03471 idealsel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[i+1],NULL));
03472 if (!sel) {
03473 Tcl_AppendResult(interp, "measure symmetry: no atom selection for idealized coordinates", NULL);
03474 bailout = 1; continue;
03475 }
03476 if (idealsel->molid()!=sel->molid()) {
03477 Tcl_AppendResult(interp, "measure symmetry: selection and idealsel must be from the same molecule", NULL);
03478 bailout = 1; continue;
03479 }
03480 if (idealsel->selected<sel->selected) {
03481 Tcl_AppendResult(interp, "measure symmetry: selection must be a subset of idealsel", NULL);
03482 bailout = 1; continue;
03483 }
03484
03485 int j;
03486 for (j=0; j<sel->num_atoms; j++) {
03487 if (sel->on[j] && !idealsel->on[j]) {
03488 Tcl_AppendResult(interp, "measure symmetry: selection must be a subset of idealsel", NULL);
03489 bailout = 1; continue;
03490 }
03491 }
03492
03493 i++;
03494 }
03495 else if (!strupncmp(argvcur, "imposeinversion", CMDLEN)) {
03496 imposeinvers = 1;
03497 impose = 1;
03498 }
03499 else if (!strupncmp(argvcur, "imposeplanes", CMDLEN)) {
03500
03501 int nelem;
03502 Tcl_Obj **elemListObj;
03503 if (i+1>=argc ||
03504 Tcl_ListObjGetElements(interp, objv[i+1], &nelem, &elemListObj) != TCL_OK) {
03505 Tcl_AppendResult(interp, " measure symmetry: bad syntax for imposeplanes option", NULL);
03506 bailout = 1; continue;
03507 }
03508 float *elem = new float[3L*nelem];
03509 int k;
03510 for (k=0; k<nelem; k++) {
03511 int nobj;
03512 Tcl_Obj **vecObj;
03513 if (Tcl_ListObjGetElements(interp, elemListObj[k], &nobj, &vecObj) != TCL_OK) {
03514 delete [] elem;
03515 Tcl_AppendResult(interp, " measure symmetry: bad syntax for imposeplanes option", NULL);
03516 bailout = 1; continue;
03517 }
03518 if (nobj!=3) {
03519 delete [] elem;
03520 Tcl_AppendResult(interp, " measure symmetry imposeplanes: vector must have 3 elements", NULL);
03521 bailout = 1; continue;
03522 }
03523
03524 int m;
03525 for (m=0; m<3; m++) {
03526 double d;
03527 if (Tcl_GetDoubleFromObj(interp, vecObj[m], &d) != TCL_OK) {
03528 delete [] elem;
03529 bailout = 1; continue;
03530 }
03531 elem[3L*k+m] = (float)d;
03532 }
03533 }
03534 if (imposeplan) delete [] imposeplan;
03535 imposeplan = elem;
03536 numimposeplan = nelem;
03537 impose = 1;
03538 i++;
03539 }
03540 else if (!strupncmp(argvcur, "imposeaxes", CMDLEN) ||
03541 !strupncmp(argvcur, "imposerotref", CMDLEN)) {
03542
03543 int nelem;
03544 Tcl_Obj **elemListObj;
03545 if (i+1>=argc ||
03546 Tcl_ListObjGetElements(interp, objv[i+1], &nelem, &elemListObj) != TCL_OK ||
03547 nelem%2) {
03548 Tcl_AppendResult(interp, " measure symmetry: bad syntax for imposeaxes/imposerotref option", NULL);
03549 bailout = 1; continue;
03550 }
03551 nelem /= 2;
03552
03553 if (nelem<=0) {
03554 i++;
03555 continue;
03556 }
03557 float *elem = new float[3L*nelem];
03558 int *axorder = new int[nelem];
03559 int k;
03560 for (k=0; k<nelem; k++) {
03561 int nobj;
03562 Tcl_Obj **vecObj;
03563 if (Tcl_ListObjGetElements(interp, elemListObj[2L*k], &nobj, &vecObj) != TCL_OK) {
03564 delete [] elem;
03565 delete [] axorder;
03566 Tcl_AppendResult(interp, " measure symmetry impose: bad syntax for axis vector", NULL);
03567 bailout = 1; continue;
03568 }
03569 if (Tcl_GetIntFromObj(interp, elemListObj[2L*k+1], &axorder[k]) != TCL_OK) {
03570 delete [] elem;
03571 delete [] axorder;
03572 bailout = 1; continue;
03573 }
03574 if (nobj!=3) {
03575 delete [] elem;
03576 delete [] axorder;
03577 Tcl_AppendResult(interp, " measure symmetry impose: axis vector must have 3 elements", NULL);
03578 bailout = 1; continue;
03579 }
03580
03581 int m;
03582 for (m=0; m<3; m++) {
03583 double d;
03584 if (Tcl_GetDoubleFromObj(interp, vecObj[m], &d) != TCL_OK) {
03585 delete [] elem;
03586 delete [] axorder;
03587 bailout = 1; continue;
03588 }
03589 elem[3L*k+m] = (float)d;
03590 }
03591 }
03592 if (!strupncmp(argvcur, "imposeaxes", CMDLEN)) {
03593 if (imposeaxes) delete [] imposeaxes;
03594 if (imposeaxesord) delete [] imposeaxesord;
03595 imposeaxes = elem;
03596 imposeaxesord = axorder;
03597 numimposeaxes = nelem;
03598 } else if (!strupncmp(argvcur, "imposerotref", CMDLEN)) {
03599 if (imposerref) delete [] imposerref;
03600 if (imposerreford) delete [] imposerreford;
03601 imposerref = elem;
03602 imposerreford = axorder;
03603 numimposerref = nelem;
03604 }
03605
03606 impose = 1;
03607 i++;
03608 }
03609 else {
03610 Tcl_AppendResult(interp, " measure symmetry: unrecognized option ", NULL);
03611 Tcl_AppendResult(interp, argvcur);
03612 Tcl_AppendResult(interp, ".\n Usage: measure symmetry <selection> [element [<vector>]] [-tol <value>] [-nobonds] [-verbose <level>]", NULL);
03613 bailout = 1; continue;
03614 }
03615 }
03616
03617 if (bailout) {
03618 if (imposeplan) delete [] imposeplan;
03619 if (imposeaxes) delete [] imposeaxes;
03620 if (imposerref) delete [] imposerref;
03621 if (imposeaxesord) delete [] imposeaxesord;
03622 if (imposerreford) delete [] imposerreford;
03623 return TCL_ERROR;
03624 }
03625 }
03626
03627
03628 Symmetry sym = Symmetry(sel, app->moleculeList, verbose);
03629
03630
03631 sym.set_overlaptol(float(sigma));
03632
03633
03634 sym.set_checkbonds(checkbonds);
03635
03636 if (checkelement) {
03637
03638
03639 float overlap = 0.0;
03640 if (checkelement==1) {
03641 overlap = sym.score_inversion();
03642 }
03643 else if (checkelement==2) {
03644 overlap = sym.score_plane(axis);
03645 }
03646 else if (checkelement==3) {
03647 overlap = sym.score_axis(axis, order);
03648 }
03649 else if (checkelement==4) {
03650 overlap = sym.score_rotary_reflection(axis, order);
03651 }
03652
03653 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
03654 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(overlap));
03655 Tcl_SetObjResult(interp, tcl_result);
03656 return TCL_OK;
03657 }
03658
03659 if (impose) {
03660 sym.impose(imposeinvers, numimposeplan, imposeplan,
03661 numimposeaxes, imposeaxes, imposeaxesord,
03662 numimposerref, imposerref, imposerreford);
03663 if (imposeplan) delete [] imposeplan;
03664 if (imposeaxes) delete [] imposeaxes;
03665 if (imposerref) delete [] imposerref;
03666 if (imposeaxesord) delete [] imposeaxesord;
03667 if (imposerreford) delete [] imposerreford;
03668 }
03669
03670 int ret_val = sym.guess(float(sigma));
03671 if (ret_val < 0) {
03672 Tcl_AppendResult(interp, "measure symmetry: ", measure_error(ret_val), NULL);
03673 return TCL_ERROR;
03674 }
03675
03676 int natoms = sel->selected;
03677 Symmetry *s = &sym;
03678
03679 if (idealsel) {
03680 Symmetry *isym = new Symmetry(idealsel, app->moleculeList, verbose);
03681 isym->set_overlaptol(float(sigma));
03682 isym->set_checkbonds(checkbonds);
03683 int j;
03684 float *plane = new float[3L*sym.numplanes()];
03685 for (j=0; j<sym.numplanes(); j++) {
03686 vec_copy(&plane[3L*j], sym.plane(j));
03687 }
03688 int *axisorder = new int[sym.numaxes()];
03689 float *axis = new float[3L*sym.numaxes()];
03690 for (j=0; j<sym.numaxes(); j++) {
03691 axisorder[j] = sym.get_axisorder(j);
03692 vec_copy(&axis[3L*j], sym.axis(j));
03693 }
03694 int *rrorder = new int[sym.numrotreflect()];
03695 float *rraxis = new float[3L*sym.numrotreflect()];
03696 for (j=0; j<sym.numrotreflect(); j++) {
03697 rrorder[j] = sym.get_rotreflectorder(j);
03698 vec_copy(&rraxis[3L*j], sym.rotreflect(j));
03699 }
03700
03701 int k=0, m=0;
03702 for (j=0; j<sel->num_atoms; j++) {
03703 if (idealsel->on[j]) {
03704 if (sel->on[j]) {
03705 vec_copy(isym->idealpos(k), sym.idealpos(m));
03706 m++;
03707 }
03708 k++;
03709 }
03710 }
03711 isym->impose(sym.has_inversion(),
03712 sym.numplanes(), plane,
03713 sym.numaxes(), axis, axisorder,
03714 sym.numrotreflect(), rraxis, rrorder);
03715
03716 ret_val = isym->guess(float(sigma));
03717 if (ret_val < 0) {
03718 Tcl_AppendResult(interp, "measure symmetry: ", measure_error(ret_val), NULL);
03719 return TCL_ERROR;
03720 }
03721
03722 natoms = idealsel->selected;
03723 s = isym;
03724 }
03725
03726 int pgorder;
03727 char pointgroup[6];
03728 s->get_pointgroup(pointgroup, &pgorder);
03729
03730 int i;
03731 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
03732 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("pointgroup", -1));
03733 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj(pointgroup, -1));
03734 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("order", -1));
03735 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewIntObj(pgorder));
03736 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("rmsd", -1));
03737 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(s->get_rmsd()));
03738 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("elements", -1));
03739 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj(s->get_element_summary(), -1));
03740 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("missing", -1));
03741 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj(s->get_missing_elements(), -1));
03742 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("additional", -1));
03743 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj(s->get_additional_elements(), -1));
03744
03745 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("com", -1));
03746 Tcl_Obj *invObj = Tcl_NewListObj(0, NULL);
03747 float *com = s->center_of_mass();
03748 Tcl_ListObjAppendElement(interp, invObj, Tcl_NewDoubleObj(com[0]));
03749 Tcl_ListObjAppendElement(interp, invObj, Tcl_NewDoubleObj(com[1]));
03750 Tcl_ListObjAppendElement(interp, invObj, Tcl_NewDoubleObj(com[2]));
03751 Tcl_ListObjAppendElement(interp, tcl_result, invObj);
03752
03753 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("inertia", -1));
03754 Tcl_Obj *inertListListObj = Tcl_NewListObj(0, NULL);
03755 float *inertia = s->get_inertia_axes();
03756 float *eigenval = s->get_inertia_eigenvals();
03757 int *unique = s->get_inertia_unique();
03758 for (i=0; i<3; i++) {
03759 Tcl_Obj *inertObj = Tcl_NewListObj(0, NULL);
03760 Tcl_ListObjAppendElement(interp, inertObj, Tcl_NewDoubleObj(inertia[3L*i]));
03761 Tcl_ListObjAppendElement(interp, inertObj, Tcl_NewDoubleObj(inertia[3L*i+1]));
03762 Tcl_ListObjAppendElement(interp, inertObj, Tcl_NewDoubleObj(inertia[3L*i+2]));
03763 Tcl_Obj *inertListObj = Tcl_NewListObj(0, NULL);
03764 Tcl_ListObjAppendElement(interp, inertListObj, inertObj);
03765 Tcl_ListObjAppendElement(interp, inertListObj, Tcl_NewDoubleObj(eigenval[i]));
03766 Tcl_ListObjAppendElement(interp, inertListObj, Tcl_NewIntObj(unique[i]));
03767 Tcl_ListObjAppendElement(interp, inertListListObj, inertListObj);
03768 }
03769 Tcl_ListObjAppendElement(interp, tcl_result, inertListListObj);
03770
03771
03772 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("inversion", -1));
03773 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewIntObj(s->has_inversion()));
03774
03775
03776 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("axes", -1));
03777 Tcl_Obj *axesListListObj = Tcl_NewListObj(0, NULL);
03778 for (i=0; i<s->numaxes(); i++) {
03779 Tcl_Obj *axesObj = Tcl_NewListObj(0, NULL);
03780
03781 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(s->axis(i)[0]));
03782 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(s->axis(i)[1]));
03783 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(s->axis(i)[2]));
03784 Tcl_Obj *axesListObj = Tcl_NewListObj(0, NULL);
03785 Tcl_ListObjAppendElement(interp, axesListObj, axesObj);
03786 Tcl_ListObjAppendElement(interp, axesListObj, Tcl_NewIntObj(s->get_axisorder(i)));
03787 int axistype = s->get_axistype(i);
03788 if (axistype & PRINCIPAL_AXIS &&
03789 !(!s->is_spherical_top() && (axistype & PERPENDICULAR_AXIS))) {
03790 Tcl_ListObjAppendElement(interp, axesListObj, Tcl_NewStringObj("principal", -1));
03791 } else if (!s->is_spherical_top() && (axistype & PERPENDICULAR_AXIS)) {
03792 Tcl_ListObjAppendElement(interp, axesListObj, Tcl_NewStringObj("perpendicular", -1));
03793 } else {
03794 Tcl_ListObjAppendElement(interp, axesListObj, Tcl_NewListObj(0, NULL));
03795 }
03796 Tcl_ListObjAppendElement(interp, axesListListObj, axesListObj);
03797 }
03798 Tcl_ListObjAppendElement(interp, tcl_result, axesListListObj);
03799
03800
03801 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("rotreflect", -1));
03802 Tcl_Obj *rraxesListListObj = Tcl_NewListObj(0, NULL);
03803 for (i=0; i<s->numrotreflect(); i++) {
03804 Tcl_Obj *axesObj = Tcl_NewListObj(0, NULL);
03805
03806 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(s->rotreflect(i)[0]));
03807 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(s->rotreflect(i)[1]));
03808 Tcl_ListObjAppendElement(interp, axesObj, Tcl_NewDoubleObj(s->rotreflect(i)[2]));
03809 Tcl_Obj *rraxesListObj = Tcl_NewListObj(0, NULL);
03810 Tcl_ListObjAppendElement(interp, rraxesListObj, axesObj);
03811 Tcl_ListObjAppendElement(interp, rraxesListObj, Tcl_NewIntObj(s->get_rotreflectorder(i)));
03812 Tcl_ListObjAppendElement(interp, rraxesListObj, Tcl_NewIntObj(s->get_rotrefltype(i)));
03813 Tcl_ListObjAppendElement(interp, rraxesListListObj, rraxesListObj);
03814 }
03815 Tcl_ListObjAppendElement(interp, tcl_result, rraxesListListObj);
03816
03817
03818 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("planes", -1));
03819 Tcl_Obj *planesListListObj = Tcl_NewListObj(0, NULL);
03820 for (i=0; i<s->numplanes(); i++) {
03821 Tcl_Obj *planesObj = Tcl_NewListObj(0, NULL);
03822
03823 Tcl_ListObjAppendElement(interp, planesObj, Tcl_NewDoubleObj(s->plane(i)[0]));
03824 Tcl_ListObjAppendElement(interp, planesObj, Tcl_NewDoubleObj(s->plane(i)[1]));
03825 Tcl_ListObjAppendElement(interp, planesObj, Tcl_NewDoubleObj(s->plane(i)[2]));
03826 Tcl_Obj *planesListObj = Tcl_NewListObj(0, NULL);
03827 Tcl_ListObjAppendElement(interp, planesListObj, planesObj);
03828 switch (s->get_planetype(i)) {
03829 case 1:
03830 Tcl_ListObjAppendElement(interp, planesListObj, Tcl_NewStringObj("vertical", -1));
03831 break;
03832 case 3:
03833 Tcl_ListObjAppendElement(interp, planesListObj, Tcl_NewStringObj("dihedral", -1));
03834 break;
03835 case 4:
03836 Tcl_ListObjAppendElement(interp, planesListObj, Tcl_NewStringObj("horizontal", -1));
03837 break;
03838 default:
03839 Tcl_ListObjAppendElement(interp, planesListObj, Tcl_NewListObj(0, NULL));
03840 }
03841 Tcl_ListObjAppendElement(interp, planesListListObj, planesListObj);
03842 }
03843 Tcl_ListObjAppendElement(interp, tcl_result, planesListListObj);
03844
03845
03846 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("ideal", -1));
03847 Tcl_Obj *idealcoorListObj = Tcl_NewListObj(0, NULL);
03848 for (i=0; i<natoms; i++) {
03849 Tcl_Obj *idealcoorObj = Tcl_NewListObj(0, NULL);
03850
03851 Tcl_ListObjAppendElement(interp, idealcoorObj, Tcl_NewDoubleObj(s->idealpos(i)[0]));
03852 Tcl_ListObjAppendElement(interp, idealcoorObj, Tcl_NewDoubleObj(s->idealpos(i)[1]));
03853 Tcl_ListObjAppendElement(interp, idealcoorObj, Tcl_NewDoubleObj(s->idealpos(i)[2]));
03854 Tcl_ListObjAppendElement(interp, idealcoorListObj, idealcoorObj);
03855 }
03856 Tcl_ListObjAppendElement(interp, tcl_result, idealcoorListObj);
03857
03858 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("unique", -1));
03859 Tcl_Obj *uniquecoorListObj = Tcl_NewListObj(0, NULL);
03860 for (i=0; i<natoms; i++) {
03861 if (!s->get_unique_atom(i)) continue;
03862 Tcl_ListObjAppendElement(interp, uniquecoorListObj, Tcl_NewIntObj(i));
03863 }
03864 Tcl_ListObjAppendElement(interp, tcl_result, uniquecoorListObj);
03865
03866 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("orient", -1));
03867 Matrix4 *orient = s->get_orientation();
03868 Tcl_Obj *matrixObj = Tcl_NewListObj(0, NULL);
03869 for (i=0; i<4; i++) {
03870 Tcl_Obj *rowObj = Tcl_NewListObj(0, NULL);
03871 Tcl_ListObjAppendElement(interp, rowObj, Tcl_NewDoubleObj(orient->mat[i+0]));
03872 Tcl_ListObjAppendElement(interp, rowObj, Tcl_NewDoubleObj(orient->mat[i+4]));
03873 Tcl_ListObjAppendElement(interp, rowObj, Tcl_NewDoubleObj(orient->mat[i+8]));
03874 Tcl_ListObjAppendElement(interp, rowObj, Tcl_NewDoubleObj(orient->mat[i+12]));
03875 Tcl_ListObjAppendElement(interp, matrixObj, rowObj);
03876 }
03877 Tcl_ListObjAppendElement(interp, tcl_result, matrixObj);
03878
03879 Tcl_SetObjResult(interp, tcl_result);
03880 if (idealsel) {
03881 delete s;
03882 }
03883 return TCL_OK;
03884
03885 }
03886
03887
03888
03889
03890
03891
03892
03893
03894
03895
03896 static int vmd_measure_trans_overlap(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
03897 if (argc!=3 && argc!=5) {
03898 Tcl_WrongNumArgs(interp, 2, objv-1, (char *) "<sel> <matrix> [-sigma <value>]");
03899 return TCL_ERROR;
03900 }
03901 AtomSel *sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
03902 if (!sel) {
03903 Tcl_AppendResult(interp, "measure transoverlap: no atom selection", NULL);
03904 return TCL_ERROR;
03905 }
03906 if (!app->molecule_valid_id(sel->molid())) {
03907 Tcl_AppendResult(interp, "measure transoverlap: ",
03908 measure_error(MEASURE_ERR_NOMOLECULE), NULL);
03909 return TCL_ERROR;
03910 }
03911
03912
03913 Matrix4 trans;
03914 if (tcl_get_matrix("measure transoverlap: ",interp,objv[2], trans.mat) != TCL_OK) {
03915 return TCL_ERROR;
03916 }
03917
03918 double sigma = 0.1;
03919 if (argc==5) {
03920 if (!strupncmp(Tcl_GetStringFromObj(objv[3],NULL), "-sigma", CMDLEN)) {
03921 if (Tcl_GetDoubleFromObj(interp, objv[4], &sigma) != TCL_OK) {
03922 Tcl_AppendResult(interp, " measure transoverlap: bad sigma value", NULL);
03923 return TCL_ERROR;
03924 }
03925 } else {
03926 Tcl_AppendResult(interp, " measure transoverlap: unrecognized option\n", NULL);
03927 Tcl_AppendResult(interp, " Usage: measure transoverlap <sel> <matrix> [-sigma <value>]", NULL);
03928 return TCL_ERROR;
03929 }
03930 }
03931
03932 int maxnatoms = 100;
03933 float overlap;
03934 int ret_val = measure_trans_overlap(sel, app->moleculeList, &trans,
03935 float(sigma), NOSKIP_IDENTICAL,
03936 maxnatoms, overlap);
03937 if (ret_val < 0) {
03938 Tcl_AppendResult(interp, "measure transoverlap: ", measure_error(ret_val), NULL);
03939 return TCL_ERROR;
03940 }
03941
03942 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
03943 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(overlap));
03944 Tcl_SetObjResult(interp, tcl_result);
03945
03946 return TCL_OK;
03947 }
03948
03949
03950
03951
03952
03953
03954 int vmd_measure_volinterior(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
03955 int verbose = 0;
03956 int recognized=0;
03957 if (argc < 3) {
03958
03959 Tcl_SetResult(interp, (char *) "usage: volinterior "
03960 " <selection1> [options]\n"
03961 "-res (default 10.0)\n"
03962 "-spacing (default res/3)\n"
03963 "-loadmap (load synth map)\n"
03964 "-probmap (compute and load probability map)\n"
03965 " --> -count_pmap (return percentile-based voxel counts)\n"
03966 "-discretize [float cutoff] (creates discrete map with cutoff probability)\n"
03967 "-mol molid [default: top]\n"
03968 "-vol volid [0]\n"
03969 "-nrays number of rays to cast [6]\n"
03970 "-isovalue [float: 1.0]\n"
03971 "-verbose\n"
03972 "-overwrite volid\n",
03973 TCL_STATIC);
03974 return TCL_ERROR;
03975 }
03976
03977
03978 AtomSel *sel = NULL;
03979 sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
03980 if (!sel) {
03981 Tcl_AppendResult(interp, "volinterior: no atom selection.", NULL);
03982 return TCL_ERROR;
03983 }
03984 if (!sel->selected) {
03985 Tcl_AppendResult(interp, "volinterior: no atoms selected.", NULL);
03986 return TCL_ERROR;
03987 }
03988 if (!app->molecule_valid_id(sel->molid())) {
03989 Tcl_AppendResult(interp, "invalid mol id.", NULL);
03990 return TCL_ERROR;
03991 }
03992 int loadsynthmap = 0;
03993 int loadpmap=0;
03994 int count_pmap=0;
03995 int print_raydirs=0;
03996 int molid = -1;
03997 int volid = -1;
03998 int volidOverwrite = -1;
03999 int overwrite=0;
04000 int nrays=6;
04001 long Nout = 0;
04002 float isovalue=1.0;
04003 float proCutoff=0.90f;
04004 int process=0;
04005 float radscale;
04006 double resolution = 10.0;
04007 double gspacing;
04008 MoleculeList *mlist = app->moleculeList;
04009 Molecule *mymol = mlist->mol_from_id(sel->molid());
04010
04011 for (int i=2; i < argc; i++) {
04012 recognized=0;
04013 char *opt = Tcl_GetStringFromObj(objv[i], NULL);
04014 if (!strcmp(opt, "volinterior")) {
04015 recognized=1;
04016 }
04017 if (!strcmp(opt, "-mol")) {
04018 if (i == argc-1) {
04019 Tcl_AppendResult(interp, "No molid specified",NULL);
04020 return TCL_ERROR;
04021 } else if ( Tcl_GetIntFromObj(interp, objv[i+1], &molid) != TCL_OK) {
04022 Tcl_AppendResult(interp, "\n molid incorrectly specified",NULL);
04023 return TCL_ERROR;
04024 }
04025 recognized=1;
04026 }
04027 if (!strcmp(opt, "-probmap")) {
04028 loadpmap=1;
04029 recognized=1;
04030 }
04031 if (!strcmp(opt, "-checkrays")) {
04032 print_raydirs=1;
04033 recognized=1;
04034 }
04035 if (!strcmp(opt, "-count_pmap")) {
04036 count_pmap=1;
04037 recognized=1;
04038 }
04039 if (!strcmp(opt, "-discretize")) {
04040 double tcutoff;
04041 if (i==argc-1) {
04042 Tcl_AppendResult(interp, "No cutoff probability given for -discretize flag",NULL);
04043 return TCL_ERROR;
04044 } else if (Tcl_GetDoubleFromObj(interp, objv[i+1], &tcutoff)!=TCL_OK) {
04045 Tcl_AppendResult(interp, "\n Cutoff probability for -discretize flag incorrectly specified.",NULL);
04046 return TCL_ERROR;
04047 }
04048 proCutoff=(float)tcutoff;
04049 recognized=1;
04050 process=1;
04051 }
04052 if (!strcmp(opt, "-vol")) {
04053 if (i == argc-1){
04054 Tcl_AppendResult(interp, "No volume id specified",NULL);
04055 return TCL_ERROR;
04056 } else if ( Tcl_GetIntFromObj(interp, objv[i+1], &volid) != TCL_OK) {
04057 Tcl_AppendResult(interp, "\n volume id incorrectly specified",NULL);
04058 return TCL_ERROR;
04059 }
04060 recognized=1;
04061 }
04062
04063 if (!strcmp(opt, "-overwrite")) {
04064 if (i == argc-1){
04065 Tcl_AppendResult(interp, "No volume id specified",NULL);
04066 return TCL_ERROR;
04067 } else if (Tcl_GetIntFromObj(interp, objv[i+1], &volidOverwrite) != TCL_OK) {
04068 Tcl_AppendResult(interp, "\n volume id incorrectly specified",NULL);
04069 return TCL_ERROR;
04070 }
04071 overwrite=1;
04072 recognized=1;
04073 }
04074
04075
04076 if (!strcmp(opt, "-loadmap")) {
04077 loadsynthmap = 1;
04078 recognized=1;
04079 }
04080 if (!strcmp(opt, "-mol")) {
04081 if (i == argc-1) {
04082 Tcl_AppendResult(interp, "No molid specified",NULL);
04083 return TCL_ERROR;
04084 } else if ( Tcl_GetIntFromObj(interp, objv[i+1], &molid) != TCL_OK) {
04085 Tcl_AppendResult(interp, "\n molid incorrectly specified",NULL);
04086 return TCL_ERROR;
04087 }
04088 recognized=1;
04089 }
04090 if (!strcmp(opt, "-res")) {
04091 if (i == argc-1) {
04092 Tcl_AppendResult(interp, "No resolution specified",NULL);
04093 return TCL_ERROR;
04094 } else if (Tcl_GetDoubleFromObj(interp, objv[i+1], &resolution) != TCL_OK) {
04095 Tcl_AppendResult(interp, "\nResolution incorrectly specified",NULL);
04096 return TCL_ERROR;
04097 }
04098 recognized=1;
04099 }
04100 if (!strcmp(opt, "-spacing")) {
04101 if (i == argc-1) {
04102 Tcl_AppendResult(interp, "No spacing specified",NULL);
04103 return TCL_ERROR;
04104 } else if ( Tcl_GetDoubleFromObj(interp, objv[i+1], &gspacing) != TCL_OK) {
04105 Tcl_AppendResult(interp, "\nspacing incorrectly specified",NULL);
04106 return TCL_ERROR;
04107 }
04108 recognized=1;
04109 }
04110
04111 if (!strcmp(opt,"-nrays")) {
04112 if (i == argc-1) {
04113 Tcl_AppendResult(interp, "No number of rays specified",NULL);
04114 return TCL_ERROR;
04115 } else if ( Tcl_GetIntFromObj(interp, objv[i+1], &nrays) != TCL_OK) {
04116 Tcl_AppendResult(interp, "\n number of rays incorrectly specified",NULL);
04117 return TCL_ERROR;
04118 }
04119 recognized=1;
04120 }
04121
04122 if (!strcmp(opt,"-isovalue")) {
04123 double tmp;
04124 if (i == argc-1) {
04125 Tcl_AppendResult(interp,"No isovalue specified",NULL);
04126 return TCL_ERROR;
04127 } else if (Tcl_GetDoubleFromObj(interp,objv[i+1],&tmp) != TCL_OK) {
04128 Tcl_AppendResult(interp,"\n Isovalue incorrectly specified", NULL);
04129 return TCL_ERROR;
04130 }
04131 isovalue=(float) tmp;
04132 recognized=1;
04133 }
04134
04135
04136
04137
04138
04139
04140
04141
04142
04143
04144
04145
04146 if (!strcmp(opt, "-verbose") || (getenv("VMDVOLINVERBOSE") != NULL)) {
04147 verbose = 1;
04148 recognized=1;
04149 }
04150
04151 if (recognized==0) {
04152
04153 if (isdigit(opt[0]) || isfloat(opt)) {
04154 continue;
04155 } else {
04156 Tcl_AppendResult(interp,"\n unrecognized option: '",opt,"'",NULL);
04157 return TCL_ERROR;
04158 }
04159 }
04160 }
04161
04162 if ((process||count_pmap) && !loadpmap) {
04163 Tcl_AppendResult(interp,"\n Cannot give -process or -count_pmap flags given without -probmap!",NULL);
04164 return TCL_ERROR;
04165 }
04166
04167 Molecule *volmolOverwrite = NULL;
04168 VolumetricData *volmapOverwrite = NULL;
04169 Molecule *pmolOverwrite=NULL;
04170 VolumetricData *pmapOverwrite=NULL;
04171 if (overwrite==1) {
04172 if (loadpmap!=1) {
04173 volmolOverwrite = mlist->mol_from_id(molid);
04174 volmapOverwrite = volmolOverwrite->modify_volume_data(volidOverwrite);
04175 if(volmapOverwrite==NULL) {
04176 Tcl_AppendResult(interp, "\n no overwrite volume correctly specified",NULL);
04177 return TCL_ERROR;
04178 }
04179 } else {
04180 pmolOverwrite=mlist->mol_from_id(molid);
04181 pmapOverwrite=pmolOverwrite->modify_volume_data(volidOverwrite);
04182 if (pmapOverwrite==NULL) {
04183 Tcl_AppendResult(interp,"\n no pmap overwrite volume correctly specified",NULL);
04184 return TCL_ERROR;
04185 }
04186 }
04187 }
04188
04189 VolumetricData *pmapT = NULL;
04190 VolumetricData *procmap = NULL;
04191 VolumetricData *pmap = NULL;
04192 VolumetricData *target = NULL;
04193 VolumetricData *volmapA = NULL;
04194
04195
04196 const float *framepos = sel->coordinates(app->moleculeList);
04197 const float *radii = mymol->radius();
04198 radscale= 0.2f * float(resolution);
04199 if (gspacing == 0) {
04200 gspacing=resolution*0.33;
04201 }
04202
04203 int quality=0;
04204 QuickSurf *qs = new QuickSurf();
04205 if (resolution >= 9)
04206 quality = 0;
04207 else
04208 quality = 3;
04209
04210 if (molid != -1 && volid != -1 ) {
04211 Molecule *volmol = mlist->mol_from_id(molid);
04212 volmapA = (VolumetricData *) volmol->get_volume_data(volid);
04213 if (volmapA==NULL) {
04214 Tcl_AppendResult(interp, "\n no target volume correctly specified", NULL);
04215 return TCL_ERROR;
04216 }
04217 } else {
04218 if (verbose) printf("\n Calculating grid ... \n");
04219 int cuda_err=-1;
04220 #if defined(VMDCUDA)
04221 cuda_err = vmd_cuda_calc_density(sel, app->moleculeList, quality,
04222 radscale, gspacing, &volmapA,
04223 NULL, NULL, verbose);
04224 #endif
04225 if (cuda_err == -1 ) {
04226 if (verbose) printf("Using CPU version of the code ... \n");
04227 volmapA = qs->calc_density_map(sel, mymol, framepos, radii,
04228 quality, radscale, float(gspacing));
04229 }
04230 if (verbose) printf("Done.\n");
04231 }
04232
04233 if (volmapA == NULL) {
04234 Tcl_AppendResult(interp, "\n no test volume or molid correctly specified",NULL);
04235 return TCL_ERROR;
04236 }
04237 target=CreateEmptyGrid(volmapA);
04238
04239 if (loadpmap == 1) {
04240 pmapT = CreateProbGrid(volmapA);
04241 }
04242
04243
04244
04245
04246
04247
04248
04249 #if 0
04250 float rayDir[3] = {1,0,0};
04251 Nout += RaycastGrid(volmapA,target,isovalue,rayDir);
04252 rayDir[0] = -1; rayDir[1]=0; rayDir[2]=0;
04253 Nout += RaycastGrid(volmapA,target,isovalue,rayDir);
04254 rayDir[0] = 0; rayDir[1]=1; rayDir[2]=0;
04255 Nout += RaycastGrid(volmapA,target,isovalue,rayDir);
04256 rayDir[0] = 0; rayDir[1]=-1; rayDir[2]=0;
04257 Nout += RaycastGrid(volmapA,target,isovalue,rayDir);
04258 rayDir[0] = 0; rayDir[1]=0; rayDir[2]=1;
04259 Nout += RaycastGrid(volmapA,target,isovalue,rayDir);
04260 rayDir[0] = 0; rayDir[1]=0; rayDir[2]=-1;
04261 Nout += RaycastGrid(volmapA,target,isovalue,rayDir);
04262 #endif
04263 #if 0
04264 if (verbose) printf("Marking down boundary.\n");
04265 long nVoxIso=markIsoGrid(volmapA, target,isovalue);
04266 if (verbose) printf("Casting rays ...\n");
04267 float rayDir[3] = {0.1f,0.1f,1.0f};
04268 Nout += volin_threaded(volmapA,target,isovalue,rayDir);
04269 if (verbose) printf("Dir 1 %ld \n",Nout);
04270 rayDir[0] = -0.1f; rayDir[1]=-0.1f; rayDir[2]=-1.0f;
04271 Nout += volin_threaded(volmapA,target,isovalue,rayDir);
04272 if (verbose) printf("Dir 2 %ld \n",Nout);
04273 rayDir[0] = 0.1f; rayDir[1]=1.0f; rayDir[2]=0.1f;
04274 Nout += volin_threaded(volmapA,target,isovalue,rayDir);
04275 if (verbose) printf("Dir 3 %ld \n",Nout);
04276 rayDir[0] = -0.1f; rayDir[1]=-1.0f; rayDir[2]=-0.1f;
04277 Nout += volin_threaded(volmapA,target,isovalue,rayDir);
04278 if (verbose) printf("Dir 4 %ld \n",Nout);
04279 rayDir[0] = 1.0f; rayDir[1]=0.1f; rayDir[2]=0.1f;
04280 Nout += volin_threaded(volmapA,target,isovalue,rayDir);
04281 if (verbose) printf("Dir 5 %ld \n",Nout);
04282 rayDir[0] = -1.0f; rayDir[1]=-0.1f; rayDir[2]=-0.1f;
04283 Nout += volin_threaded(volmapA,target,isovalue,rayDir);
04284 if (verbose) printf("Dir 6 %ld \n",Nout);
04285 rayDir[0] = -0.5f; rayDir[1]=-0.5f; rayDir[2]=-0.5f;
04286 Nout += volin_threaded(volmapA,target,isovalue,rayDir);
04287 if (verbose) printf("Dir 7 %ld \n",Nout);
04288 rayDir[0] = 0.5f; rayDir[1]=0.5f; rayDir[2]=0.5f;
04289 Nout += volin_threaded(volmapA,target,isovalue,rayDir);
04290 if (verbose) printf("Dir 9 %ld \n",Nout);
04291 rayDir[0] = -0.5f; rayDir[1]=0.5f; rayDir[2]=0.5f;
04292 Nout += volin_threaded(volmapA,target,isovalue,rayDir);
04293 if (verbose) printf("Dir 10 %ld \n",Nout);
04294 rayDir[0] = 0.5f; rayDir[1]=-0.5f; rayDir[2]=0.5f;
04295 Nout += volin_threaded(volmapA,target,isovalue,rayDir);
04296 if (verbose) printf("Dir 11 %ld \n",Nout);
04297 rayDir[0] = 0.5f; rayDir[1]=0.5f; rayDir[2]=-0.5f;
04298 Nout += volin_threaded(volmapA,target,isovalue,rayDir);
04299 if (verbose) printf("Dir 12 %ld \n",Nout);
04300 #endif
04301 if (verbose) printf("Marking down boundary.\n");
04302 long nVoxIso=markIsoGrid(volmapA, target,isovalue);
04303 float rayDir[3] = {0.1f,0.1f,1.0f};
04304 static const float RAND_MAX_INV = 1.0f/float(VMD_RAND_MAX);
04305
04306 float *poisson_set = new float[(nrays+1)*2];
04307 int numcandidates=40;
04308 int converged=poisson_sample_on_sphere(poisson_set,nrays,numcandidates,verbose);
04309 if (converged==0) {
04310 if (verbose) {
04311 printf("Poisson disk sampler failed for measure volinterior!\n");
04312 printf("... continuing with standard ray direction generator.\n");
04313 }
04314 }
04315
04316 if (print_raydirs && converged)
04317 print_xyz(poisson_set,nrays);
04318
04319 if (verbose) printf("Casting rays...\n");
04320
04321
04322
04323
04324
04325
04326
04327
04328
04329
04330
04331 float sine1, cosine1, sine2, cosine2;
04332 for (int ray=0; ray < nrays; ray++) {
04333 float u1 = (float) vmd_random();
04334 float u2 = (float) vmd_random();
04335 float z = 2.0f*u1*RAND_MAX_INV -1.0f;
04336 float phi = (float) (2.0f*VMD_PI*u2*RAND_MAX_INV);
04337 float R = sqrtf(1.0f-z*z);
04338 if (converged==1) {
04339 sincosf(poisson_set[ray*2+0],&sine1,&cosine1);
04340 sincosf(poisson_set[ray*2+1],&sine2,&cosine2);
04341 rayDir[0]=cosine1*sine2;
04342 rayDir[1]=sine1*sine2;
04343 rayDir[2]=cosine2;
04344 } else {
04345 sincosf(phi,&sine1,&cosine1);
04346 rayDir[0]=R*cosine1;
04347 rayDir[1]=R*sine1;
04348 rayDir[2]=z;
04349 }
04350
04351
04352
04353
04354
04355 if (loadpmap == 1) {
04356 Nout += volin_threaded_prob(volmapA, target, pmapT, isovalue, rayDir);
04357 } else {
04358 Nout += volin_threaded(volmapA, target, isovalue, rayDir);
04359 }
04360
04361 if (verbose) printf("Ray(%d) (%4.3f %4.3f %4.3f). Voxels : %ld \n",ray+1,rayDir[0],rayDir[1],rayDir[2],Nout);
04362 }
04363 if (verbose) printf("Done.\n");
04364
04365 delete [] poisson_set;
04366
04367 if (verbose) printf("Counting voxels above isovalue ...\n");
04368
04369 Nout=countIsoGrids(target,EXTERIORVOXEL);
04370 long nIn=countIsoGrids(target,INTERIORVOXEL);
04371
04372 if (loadsynthmap == 1 ) {
04373 app->molecule_add_volumetric(molid, volmapA->name, volmapA->origin,
04374 volmapA->xaxis, volmapA->yaxis, volmapA->zaxis,
04375 volmapA->xsize, volmapA->ysize, volmapA->zsize,
04376 volmapA->data);
04377 volmapA->compute_volume_gradient();
04378 volmapA->data = NULL;
04379 }
04380
04381 if (overwrite != 1 ) {
04382 if (loadpmap==1) {
04383 if (verbose) printf("Normalizing probability map ...\n");
04384 pmap = normalize_pmap(pmapT, nrays);
04385 app->molecule_add_volumetric(molid, pmap->name, pmap->origin,
04386 pmap->xaxis, pmap->yaxis, pmap->zaxis,
04387 pmap->xsize, pmap->ysize, pmap->zsize,
04388 pmap->data);
04389 pmap->compute_volume_gradient();
04390 } else {
04391 app->molecule_add_volumetric(molid, target->name, target->origin,
04392 target->xaxis, target->yaxis, target->zaxis,
04393 target->xsize, target->ysize, target->zsize,
04394 target->data);
04395 target->compute_volume_gradient();
04396 target->data = NULL;
04397 }
04398 } else {
04399 if (loadpmap==1) {
04400 if (verbose) printf("Normalizing probability map ...\n");
04401 pmap = normalize_pmap(pmapT, nrays);
04402 if (verbose) printf("Overwriting volume...\n");
04403 pmapOverwrite->name=pmap->name;
04404 pmapOverwrite->xsize=pmap->xsize;
04405 pmapOverwrite->ysize=pmap->ysize;
04406 pmapOverwrite->zsize=pmap->zsize;
04407 pmapOverwrite->data=pmap->data;
04408 pmap->data=NULL;
04409 pmapOverwrite->compute_volume_gradient();
04410 if (verbose) printf("Done!\n");
04411 } else {
04412 if (verbose) printf("Overwriting volume ... \n");
04413 volmapOverwrite->name = target -> name;
04414 volmapOverwrite->xsize = target->xsize;
04415 volmapOverwrite->ysize = target->ysize;
04416 volmapOverwrite->zsize = target->zsize;
04417 volmapOverwrite->data = target->data;
04418 target->data=NULL;
04419 volmapOverwrite->compute_volume_gradient();
04420 if (verbose) printf("Done.\n ");
04421 }
04422 }
04423
04424 if ((loadpmap&&process)&&pmap->data!=NULL) {
04425
04426 procmap=process_pmap(pmap, proCutoff);
04427 app->molecule_add_volumetric(molid, procmap->name, procmap->origin,
04428 procmap->xaxis, procmap->yaxis, procmap->zaxis,
04429 procmap->xsize, procmap->ysize, procmap->zsize, procmap->data);
04430 procmap->compute_volume_gradient();
04431 procmap->data=NULL;
04432 if (verbose) printf("Loaded processed map\n");
04433 } else if ((loadpmap&&process)&&pmapOverwrite->data!=NULL) {
04434 procmap=process_pmap(pmapOverwrite, proCutoff);
04435 app->molecule_add_volumetric(molid, procmap->name, procmap->origin,
04436 procmap->xaxis, procmap->yaxis, procmap->zaxis,
04437 procmap->xsize, procmap->ysize, procmap->zsize, procmap->data);
04438 procmap->compute_volume_gradient();
04439 procmap->data=NULL;
04440 if (verbose) printf("Loaded processed map (they don't overwrite).\n");
04441 }
04442
04443 if (count_pmap==1 && pmap->data!=NULL) {
04444 if (loadpmap!=1) {
04445 printf("-count_pmap flag specified without -probmap!\n");
04446 return TCL_ERROR;
04447 } else {
04448 long Pvol=0;
04449 float currProb=0.0f;
04450 Tcl_Obj *analysis=Tcl_NewListObj(0,NULL);
04451 for (int c=0; c<10; c++) {
04452 currProb+=0.1f;
04453 if (c==9) currProb=((float)nrays-((float)nrays*0.01f))/(float)nrays;
04454 Pvol=vol_probability(pmap, currProb, float(gspacing));
04455 Tcl_ListObjAppendElement(interp, analysis, Tcl_NewLongObj(Pvol));
04456 }
04457 Tcl_SetObjResult(interp,analysis);
04458 if (molid != -1 && volid != -1 ) {
04459 target->data = NULL;
04460 pmap->data = NULL;
04461 } else {
04462 delete pmapT;
04463 delete qs;
04464 delete volmapA;
04465 }
04466
04467 return TCL_OK;
04468 }
04469 } else if (count_pmap==1 && overwrite==1 && pmapOverwrite->data!=NULL) {
04470 long Pvol=0;
04471 float currProb=0.0f;
04472 Tcl_Obj *analysis=Tcl_NewListObj(0,NULL);
04473 for (int c=0; c<10; c++) {
04474 currProb+=0.1f;
04475 if (c==9) currProb=((float)nrays-((float)nrays*0.01f))/(float)nrays;
04476 Pvol=vol_probability(pmapOverwrite, currProb, float(gspacing));
04477 Tcl_ListObjAppendElement(interp, analysis, Tcl_NewLongObj(Pvol));
04478 }
04479 Tcl_SetObjResult(interp,analysis);
04480 if (molid != -1 && volid != -1 ) {
04481 target->data = NULL;
04482 pmap->data = NULL;
04483 } else {
04484 delete pmapT;
04485 delete qs;
04486 delete volmapA;
04487 }
04488
04489 return TCL_OK;
04490 }
04491
04492 if (molid != -1 && volid != -1 ) {
04493 target->data = NULL;
04494 procmap->data=NULL;
04495 pmap->data = NULL;
04496 } else {
04497 delete pmapT;
04498 delete qs;
04499 delete volmapA;
04500 }
04501
04502 long Ntotal = target->xsize * target->ysize * target->zsize;
04503
04504
04505 Tcl_Obj *tcl_result = Tcl_NewListObj(0,NULL);
04506 Tcl_ListObjAppendElement(interp,tcl_result,Tcl_NewLongObj(Ntotal));
04507 Tcl_ListObjAppendElement(interp,tcl_result,Tcl_NewLongObj(Nout));
04508 Tcl_ListObjAppendElement(interp,tcl_result,Tcl_NewLongObj(nIn));
04509 Tcl_ListObjAppendElement(interp,tcl_result,Tcl_NewLongObj(nVoxIso));
04510 Tcl_SetObjResult(interp,tcl_result);
04511 return TCL_OK;
04512 }
04513
04514 int obj_measure(ClientData cd, Tcl_Interp *interp, int argc,
04515 Tcl_Obj * const objv[]) {
04516
04517 if (argc < 2) {
04518 Tcl_SetResult(interp,
04519 (char *) "usage: measure <command> [args...]\n"
04520 "\nMeasure Commands:\n"
04521 " avpos <sel> [first <first>] [last <last>] [step <step>] -- average position\n"
04522 " center <sel> [weight <weights>] -- geometrical (or weighted) center\n"
04523 " centerperresidue <sel> [weight <weights>] -- geometrical center for every residue in sel\n"
04524 " cluster <sel> [num <#clusters>] [distfunc <flag>] [cutoff <cutoff>]\n"
04525 " [first <first>] [last <last>] [step <step>] [selupdate <bool>]\n"
04526 " [weight <weights>]\n"
04527 " -- perform a cluster analysis (cluster similar timesteps)\n"
04528 " clustsize <sel> [cutoff <float>] [minsize <num>] [numshared <num>]\n"
04529 " [usepbc <bool>] [storesize <fieldname>] [storenum <fieldname>]\n"
04530 " -- perform a cluster size analysis (find clusters of atoms)\n"
04531 " contacts <cutoff> <sel1> [<sel2>] -- list contacts\n"
04532 " dipole <sel> [-elementary|-debye] [-geocenter|-masscenter|-origincenter]\n"
04533 " -- dipole moment\n"
04534 " fit <sel1> <sel2> [weight <weights>] [order <index list>]\n"
04535 " -- transformation matrix from selection 1 to 2\n"
04536 " gofr <sel1> <sel2> [delta <value>] [rmax <value>] [usepbc <bool>]\n"
04537 " [selupdate <bool>] [first <first>] [last <last>] [step <step>]\n"
04538 " -- atomic pair distribution function g(r)\n"
04539 " hbonds <cutoff> <angle> <sel1> [<sel2>]\n"
04540 " -- list donors, acceptors, hydrogens involved in hydrogen bonds\n"
04541 " inverse <matrix> -- inverse matrix\n"
04542 " inertia <sel> [-moments] [-eigenvals] -- COM and principle axes of inertia\n"
04543 " minmax <sel> [-withradii] -- bounding box\n"
04544 " rgyr <sel> [weight <weights>] -- radius of gyration\n"
04545 " rmsd <sel1> <sel2> [weight <weights>] -- RMS deviation\n"
04546 " rmsdperresidue <sel1> <sel2> [weight <weights>] -- deviation per residue\n"
04547 " rmsf <sel> [first <first>] [last <last>] [step <step>] -- RMS fluctuation\n"
04548 " rmsfperresidue <sel> [first <first>] [last <last>] [step <step>] -- fluctuation per residue\n"
04549 " sasa <srad> <sel> [-points <varname>] [-restrict <restrictedsel>]\n"
04550 " [-samples <numsamples>] -- solvent-accessible surface area\n"
04551 " sumweights <sel> weight <weights> -- sum of selected weights\n"
04552 " bond {{<atomid1> [<molid1>]} {<atomid2> [<molid2>]}}\n"
04553 " [molid <default mol>] [frame <frame|all|last> | first <first> last <last>]\n"
04554 " -- bond length between atoms 1 and 2\n"
04555 " angle {{<atomid1> [<molid1>]} {<atomid2> [<molid2>]} {<atomid3> [<molid3>]}}\n"
04556 " [molid <default mol>] [frame <frame|all|last> | first <first> last <last>]\n"
04557 " -- angle between atoms 1-3\n"
04558 " dihed {{<atomid1> [<molid1>]} ... {<atomid4> [<molid4>]}}\n"
04559 " [molid <default mol>] [frame <frame|all|last> | first <first> last <last>]\n"
04560 " -- dihedral angle between atoms 1-4\n"
04561 " imprp {{<atomid1> [<molid1>]} ... {<atomid4> [<molid4>]}}\n"
04562 " [molid <default mol>] [frame <frame|all|last> | first <first> last <last>]\n"
04563 " -- improper angle between atoms 1-4\n"
04564
04565 " energy bond|angle|dihed|impr|vdw|elec -- compute energy\n"
04566 " surface <sel> <gridsize> <radius> <thickness> -- surface of selection\n"
04567 " pbc2onc <center> [molid <default>] [frame <frame|last>]\n"
04568 " -- transformation matrix to wrap a nonorthogonal PBC unit cell\n"
04569 " into an orthonormal cell\n"
04570 " pbcneighbors <center> <cutoff> [sel <sel>] [align <matrix>] [molid <default>]\n"
04571 " [frame <frame|last>] [boundingbox <PBC|{<mincoord> <maxcoord>}>]\n"
04572 " -- all image atoms that are within cutoff Angstrom of the pbc unit cell\n"
04573 " symmetry <sel> [element [<vector>]] [-tol <value>] [-nobonds] [-verbose <level>]\n"
04574 " transoverlap <sel> <matrix> [-sigma <value>]\n"
04575 " -- overlap of a structure with a transformed copy of itself\n"
04576 " volinterior <sel> [options]\n"
04577 " -- type 'measure volinterior' for usage\n",
04578 TCL_STATIC);
04579 return TCL_ERROR;
04580 }
04581 VMDApp *app = (VMDApp *)cd;
04582 char *argv1 = Tcl_GetStringFromObj(objv[1],NULL);
04583 if (!strupncmp(argv1, "avpos", CMDLEN))
04584 return vmd_measure_avpos(app, argc-1, objv+1, interp);
04585 else if (!strupncmp(argv1, "center", CMDLEN))
04586 return vmd_measure_center(app, argc-1, objv+1, interp);
04587 #if 1
04588
04589 else if (!strupncmp(argv1, "centerperresidue", CMDLEN))
04590 return vmd_measure_centerperresidue(app, argc-1, objv+1, interp);
04591 #endif
04592 else if (!strupncmp(argv1, "cluster", CMDLEN))
04593 return vmd_measure_cluster(app, argc-1, objv+1, interp);
04594 else if (!strupncmp(argv1, "clustsize", CMDLEN))
04595 return vmd_measure_clustsize(app, argc-1, objv+1, interp);
04596 else if (!strupncmp(argv1, "contacts", CMDLEN))
04597 return vmd_measure_contacts(app, argc-1, objv+1, interp);
04598 else if (!strupncmp(argv1, "dipole", CMDLEN))
04599 return vmd_measure_dipole(app, argc-1, objv+1, interp);
04600 else if (!strupncmp(argv1, "fit", CMDLEN))
04601 return vmd_measure_fit(app, argc-1, objv+1, interp);
04602 else if (!strupncmp(argv1, "minmax", CMDLEN))
04603 return vmd_measure_minmax(app, argc-1, objv+1, interp);
04604 else if (!strupncmp(argv1, "gofr", CMDLEN))
04605 return vmd_measure_gofr(app, argc-1, objv+1, interp);
04606 else if (!strupncmp(argv1, "rdf", CMDLEN))
04607 return vmd_measure_rdf(app, argc-1, objv+1, interp);
04608 else if (!strupncmp(argv1, "hbonds", CMDLEN))
04609 return vmd_measure_hbonds(app, argc-1, objv+1, interp);
04610 else if (!strupncmp(argv1, "inverse", CMDLEN))
04611 return vmd_measure_inverse(argc-1, objv+1, interp);
04612 else if (!strupncmp(argv1, "inertia", CMDLEN))
04613 return vmd_measure_inertia(app, argc-1, objv+1, interp);
04614 else if (!strupncmp(argv1, "rgyr", CMDLEN))
04615 return vmd_measure_rgyr(app, argc-1, objv+1, interp);
04616 else if (!strupncmp(argv1, "rmsd", CMDLEN))
04617 return vmd_measure_rmsd(app, argc-1, objv+1, interp);
04618 #if 1
04619
04620 else if (!strupncmp(argv1, "rmsdperresidue", CMDLEN))
04621 return vmd_measure_rmsdperresidue(app, argc-1, objv+1, interp);
04622 #endif
04623 #if 1
04624 else if (!strupncmp(argv1, "rmsd_qcp", CMDLEN))
04625 return vmd_measure_rmsd_qcp(app, argc-1, objv+1, interp);
04626 else if (!strupncmp(argv1, "rmsdmat_qcp", CMDLEN))
04627 return vmd_measure_rmsdmat_qcp(app, argc-1, objv+1, interp);
04628 else if (!strupncmp(argv1, "rmsdmat_qcp_ooc", CMDLEN))
04629 return vmd_measure_rmsdmat_qcp_ooc(app, argc-1, objv+1, interp);
04630 #endif
04631 else if (!strupncmp(argv1, "rmsf", CMDLEN))
04632 return vmd_measure_rmsf(app, argc-1, objv+1, interp);
04633 #if 1
04634
04635 else if (!strupncmp(argv1, "rmsfperresidue", CMDLEN))
04636 return vmd_measure_rmsfperresidue(app, argc-1, objv+1, interp);
04637 #endif
04638 else if (!strupncmp(argv1, "sasa", CMDLEN))
04639 return vmd_measure_sasa(app, argc-1, objv+1, interp);
04640 #if 1
04641 else if (!strupncmp(argv1, "sasalist", CMDLEN))
04642 return vmd_measure_sasalist(app, argc-1, objv+1, interp);
04643 #endif
04644 else if (!strupncmp(argv1, "sumweights", CMDLEN))
04645 return vmd_measure_sumweights(app, argc-1, objv+1, interp);
04646 else if (!strupncmp(argv1, "imprp", CMDLEN))
04647 return vmd_measure_dihed(app, argc-1, objv+1, interp);
04648 else if (!strupncmp(argv1, "dihed", CMDLEN))
04649 return vmd_measure_dihed(app, argc-1, objv+1, interp);
04650 else if (!strupncmp(argv1, "angle", CMDLEN))
04651 return vmd_measure_angle(app, argc-1, objv+1, interp);
04652 else if (!strupncmp(argv1, "bond", CMDLEN))
04653 return vmd_measure_bond(app, argc-1, objv+1, interp);
04654 else if (!strupncmp(argv1, "energy", CMDLEN))
04655 return vmd_measure_energy(app, argc-1, objv+1, interp);
04656 else if (!strupncmp(argv1, "pbc2onc", CMDLEN))
04657 return vmd_measure_pbc2onc_transform(app, argc-1, objv+1, interp);
04658 else if (!strupncmp(argv1, "pbcneighbors", CMDLEN))
04659 return vmd_measure_pbc_neighbors(app, argc-1, objv+1, interp);
04660 else if (!strupncmp(argv1, "surface", CMDLEN))
04661 return vmd_measure_surface(app, argc-1, objv+1, interp);
04662 else if (!strupncmp(argv1, "transoverlap", CMDLEN))
04663 return vmd_measure_trans_overlap(app, argc-1, objv+1, interp);
04664 else if (!strupncmp(argv1, "symmetry", CMDLEN))
04665 return vmd_measure_symmetry(app, argc-1, objv+1, interp);
04666 else if (!strupncmp(argv1, "volinterior", CMDLEN))
04667 return vmd_measure_volinterior(app, argc-1, objv+1, interp);
04668
04669 Tcl_SetResult(interp, (char *) "Type 'measure' for summary of usage\n", TCL_VOLATILE);
04670 return TCL_OK;
04671 }
04672
04673
04674