00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <tcl.h>
00022 #include <ctype.h>
00023 #include "config.h"
00024 #include "VMDApp.h"
00025 #include "MoleculeList.h"
00026 #include "TclCommands.h"
00027 #include "Animation.h"
00028
00029 static void cmd_animate_usage(Tcl_Interp *interp) {
00030 Tcl_AppendResult(interp,
00031 "usage: animate <command> [args...]"
00032 "animate styles\n"
00033 "animate style [once|rock|loop]\n"
00034 "animate dup [|frame <number>] <molecule id>\n"
00035 "animate goto [start|end|<num]\n"
00036 "animate [reverse|rev|forward|for|prev|next|pause]\n"
00037 "animate [speed|skip] [|<value>]\n"
00038 "animate delete all\n"
00039 "animate delete [|beg <num>] [|end <num>] [|skip <num>] <molecule id>\n"
00040 "animate [read|write] <file type> <filename>\n"
00041 " [|beg <num>] [|end <num>] [|skip <num>] [|waitfor <num/all>]\n"
00042 " [|sel <atom selection>] [|<molecule id>]",
00043 NULL);
00044 }
00045
00046 int text_cmd_animate(ClientData cd, Tcl_Interp *interp, int argc,
00047 const char *argv[]) {
00048
00049 VMDApp *app = (VMDApp *)cd;
00050
00051
00052
00053 if (argc == 1) {
00054 cmd_animate_usage(interp);
00055 }
00056
00057 if (argc == 2) {
00058 if (!strupncmp(argv[1], "styles", CMDLEN)) {
00059
00060 size_t loop = 0;
00061 while(loop < sizeof(animationStyleName) / sizeof(char*)) {
00062 Tcl_AppendElement(interp, animationStyleName[loop++]);
00063 }
00064 return TCL_OK;
00065 }
00066 if (!strupncmp(argv[1], "skip", CMDLEN)) {
00067 Tcl_SetObjResult(interp, Tcl_NewIntObj(app->anim->skip()));
00068 return TCL_OK;
00069 }
00070 if (!strupncmp(argv[1], "speed", CMDLEN)) {
00071 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(app->anim->speed()));
00072 return TCL_OK;
00073 }
00074 if (!strupncmp(argv[1], "style", CMDLEN)) {
00075 int style = app->anim->anim_style();
00076 Tcl_AppendElement(interp, animationStyleName[style]);
00077 return TCL_OK;
00078 }
00079
00080 }
00081
00082 if ((argc == 3 || argc == 5) && !strupncmp(argv[1], "dup", CMDLEN)) {
00083
00084
00085
00086
00087 int frame = -1;
00088 int molid = -1;
00089
00090 if (argc == 3) {
00091 if (!strcmp(argv[2], "top")) {
00092 if (app->moleculeList -> top()) {
00093 molid = app->moleculeList -> top() -> id();
00094 } else {
00095 molid = -1;
00096 }
00097 } else if (Tcl_GetInt(interp, argv[2], &molid) != TCL_OK) {
00098 Tcl_AppendResult(interp, " in animate dup", NULL);
00099 return TCL_ERROR;
00100 }
00101
00102 } else {
00103 if (strcmp(argv[2], "frame")) {
00104
00105 Tcl_AppendResult(interp,
00106 "format is: animate dup [frame <number>] <molecule id>",NULL);
00107 return TCL_ERROR;
00108 }
00109 if (!strcmp(argv[3], "now")) {
00110 frame = -1;
00111 } else if (!strcmp(argv[3], "null")) {
00112 frame = -2;
00113 } else {
00114 if (Tcl_GetInt(interp, argv[3], &frame) != TCL_OK) {
00115 Tcl_AppendResult(interp, " in animate dup frame", NULL);
00116 return TCL_ERROR;
00117 }
00118 }
00119 if (Tcl_GetInt(interp, argv[4], &molid) != TCL_OK) {
00120 Tcl_AppendResult(interp, " in animate dup", NULL);
00121 return TCL_ERROR;
00122 }
00123 }
00124 if (!app->molecule_dupframe(molid, frame)) return TCL_ERROR;
00125 return TCL_OK;
00126 }
00127
00128
00129 if (argc == 2) {
00130 Animation::AnimDir newDir;
00131 if(!strupncmp(argv[1], "reverse", CMDLEN) ||
00132 !strupncmp(argv[1], "rev", CMDLEN))
00133 newDir = Animation::ANIM_REVERSE;
00134 else if(!strupncmp(argv[1], "forward", CMDLEN) ||
00135 !strupncmp(argv[1], "for", CMDLEN))
00136 newDir = Animation::ANIM_FORWARD;
00137 else if(!strupncmp(argv[1], "prev", CMDLEN))
00138 newDir = Animation::ANIM_REVERSE1;
00139 else if(!strupncmp(argv[1], "next", CMDLEN))
00140 newDir = Animation::ANIM_FORWARD1;
00141 else if(!strupncmp(argv[1], "pause", CMDLEN))
00142 newDir = Animation::ANIM_PAUSE;
00143 else {
00144 cmd_animate_usage(interp);
00145 return TCL_ERROR;
00146 }
00147 app->animation_set_dir(newDir);
00148 } else if(argc == 3) {
00149 if(!strupncmp(argv[1], "skip", CMDLEN)) {
00150 int tmp;
00151 if (Tcl_GetInt(interp, argv[2], &tmp) != TCL_OK) {
00152 Tcl_AppendResult(interp, " in animate skip", NULL);
00153 return TCL_ERROR;
00154 }
00155 app->animation_set_stride(tmp);
00156 } else if(!strupncmp(argv[1], "delete", CMDLEN)) {
00157 if(!strupncmp(argv[2], "all", CMDLEN)) {
00158 int molid = app->molecule_top();
00159 int last = app->molecule_numframes(molid)-1;
00160 int rc = app->molecule_deleteframes(molid, 0, last, -1);
00161 return rc ? TCL_OK : TCL_ERROR;
00162 } else {
00163 cmd_animate_usage(interp);
00164 return TCL_ERROR;
00165 }
00166 } else if(!strupncmp(argv[1], "speed", CMDLEN))
00167 app->animation_set_speed((float) atof(argv[2]));
00168 else if(!strupncmp(argv[1], "style", CMDLEN)) {
00169 int newStyle = Animation::ANIM_ONCE;
00170 Animation::AnimStyle enumVal;
00171 while(newStyle < Animation::ANIM_TOTAL_STYLES) {
00172 if(!strupncmp(argv[2], animationStyleName[newStyle], CMDLEN))
00173 break;
00174 newStyle++;
00175 }
00176 if(newStyle == Animation::ANIM_ONCE)
00177 enumVal = Animation::ANIM_ONCE;
00178 else if(newStyle == Animation::ANIM_ROCK)
00179 enumVal = Animation::ANIM_ROCK;
00180 else if(newStyle == Animation::ANIM_LOOP)
00181 enumVal = Animation::ANIM_LOOP;
00182 else {
00183 Tcl_AppendResult(interp,
00184 "Unknown animate style '" ,argv[2] ,"'\n",NULL);
00185 Tcl_AppendResult(interp, "Valid styles are: ", NULL);
00186 newStyle = Animation::ANIM_ONCE;
00187 while(newStyle < Animation::ANIM_TOTAL_STYLES) {
00188 Tcl_AppendElement(interp, animationStyleName[newStyle]);
00189 newStyle ++;
00190 }
00191 return TCL_ERROR;
00192 }
00193 app->animation_set_style(enumVal);
00194 } else if(!strupncmp(argv[1], "goto", CMDLEN)) {
00195 int newframe;
00196 if(!strupncmp(argv[2], "start", CMDLEN))
00197 newframe = -1;
00198 else if(!strupncmp(argv[2], "end", CMDLEN))
00199 newframe = -2;
00200 else if(isdigit(argv[2][0]))
00201 newframe = atoi(argv[2]);
00202 else {
00203 Tcl_AppendResult(interp,
00204 "Bad goto parameter '" ,argv[2] ,"'\n",NULL);
00205 Tcl_AppendResult(interp,
00206 "Valid values are a non-negative number, 'start', or 'end'.",NULL);
00207 return TCL_ERROR;
00208 }
00209 app->animation_set_frame(newframe);
00210 } else {
00211 cmd_animate_usage(interp);
00212 return TCL_ERROR;
00213 }
00214 } else if(argc >= 4) {
00215 int bf = 0, ef = (-1), fs = 1, mid = (-1);
00216 const char *fileType = NULL;
00217 const char *fileName = NULL;
00218 int do_action = (-1);
00219 int currarg = 1;
00220 int waitfor = 1;
00221
00222
00223 if(!strupncmp(argv[currarg], "read", CMDLEN)) {
00224 do_action = 0;
00225 } else if(!strupncmp(argv[currarg], "write", CMDLEN)) {
00226 do_action = 1;
00227 waitfor = -1;
00228 } else if(!strupncmp(argv[currarg], "delete", CMDLEN)) {
00229 do_action = 2;
00230 fs = -1;
00231 } else {
00232 cmd_animate_usage(interp);
00233 return TCL_ERROR;
00234 }
00235 currarg++;
00236
00237
00238 if(do_action == 0 || do_action == 1) {
00239 fileType = argv[currarg++];
00240 fileName = argv[currarg++];
00241 }
00242
00243 AtomSel *selection = NULL;
00244 ResizeArray<int> volsets;
00245 mid = app->molecule_top();
00246
00247 while(currarg < argc) {
00248 if(currarg < (argc - 1)) {
00249 if(!strupncmp(argv[currarg], "beg", CMDLEN)) {
00250 bf = atoi(argv[currarg+1]);
00251 currarg += 2;
00252 } else if(!strupncmp(argv[currarg], "end", CMDLEN)) {
00253 ef = atoi(argv[currarg+1]);
00254 currarg += 2;
00255 } else if(!strupncmp(argv[currarg], "skip", CMDLEN)) {
00256 fs = atoi(argv[currarg+1]);
00257 currarg += 2;
00258 } else if(do_action == 2 && argc == 4 && currarg == 2 &&
00259 !strupncmp(argv[currarg], "all", CMDLEN)) {
00260 if (strcmp(argv[currarg+1], "top"))
00261 mid = atoi(argv[currarg+1]);
00262 else
00263 mid = app->molecule_top();
00264 currarg += 2;
00265 } else if ((do_action == 0 || do_action == 1) &&
00266 !strupncmp(argv[currarg], "waitfor", CMDLEN)) {
00267 const char *arg = argv[currarg+1];
00268 if (!strupncmp(arg, "all", CMDLEN))
00269 waitfor = -1;
00270 else
00271 waitfor = atoi(arg);
00272 currarg += 2;
00273 } else if (do_action == 1 &&
00274 !strupncmp(argv[currarg], "sel", CMDLEN)) {
00275
00276 const char *selstr = argv[currarg+1];
00277 if (!(selection = tcl_commands_get_sel(interp, selstr))) {
00278 Tcl_AppendResult(interp, "Invalid atom selection ", selstr);
00279 return TCL_ERROR;
00280 }
00281 currarg += 2;
00282 } else if (do_action == 1 &&
00283 !strupncmp(argv[currarg], "volsets", CMDLEN)) {
00284
00285 const char *volstr = argv[currarg+1];
00286 int nsets;
00287 const char **setstrs;
00288 if (Tcl_SplitList(interp, volstr, &nsets, &setstrs) != TCL_OK) {
00289 Tcl_AppendResult(interp, "Invalid volset argument: ", volstr);
00290 return TCL_ERROR;
00291 }
00292 for (int i=0; i<nsets; i++) {
00293 int tmp;
00294 if (Tcl_GetInt(interp, setstrs[i], &tmp) != TCL_OK) {
00295 Tcl_Free((char *)setstrs);
00296 return TCL_ERROR;
00297 }
00298 volsets.append(tmp);
00299 }
00300 Tcl_Free((char *)setstrs);
00301 currarg += 2;
00302 } else
00303 return TCL_ERROR;
00304 } else {
00305
00306 if (strcmp(argv[currarg], "top")) {
00307 mid = atoi(argv[currarg++]);
00308 } else {
00309 mid = app->molecule_top();
00310 currarg++;
00311 }
00312 }
00313 }
00314
00315
00316
00317
00318 if (selection) {
00319 if (mid != selection->molid()) {
00320 Tcl_SetResult(interp, "ERROR: animate: Molecule in selection must match animation molecule.", TCL_STATIC);
00321 return TCL_ERROR;
00322 }
00323 }
00324
00325
00326 FileSpec spec;
00327 spec.first = bf;
00328 spec.last = ef;
00329 spec.stride = fs;
00330 spec.waitfor = waitfor;
00331 if (do_action == 0) {
00332 int rc = app->molecule_load(mid, fileName, fileType, &spec);
00333 if (rc < 0) return TCL_ERROR;
00334
00335 } else if (do_action == 1) {
00336 spec.selection = selection ? selection->on : NULL;
00337 if (volsets.num()) {
00338
00339 spec.nvolsets = volsets.num();
00340 spec.setids = new int[spec.nvolsets];
00341 for (int i=0; i<spec.nvolsets; i++) spec.setids[i] = volsets[i];
00342 }
00343 int numwritten = app->molecule_savetrajectory(mid, fileName, fileType,
00344 &spec);
00345 if (numwritten < 0) return TCL_ERROR;
00346 Tcl_SetObjResult(interp, Tcl_NewIntObj(numwritten));
00347
00348 } else if (do_action == 2)
00349 app->molecule_deleteframes(mid, bf, ef, fs);
00350
00351 else
00352 return TCL_ERROR;
00353
00354 } else
00355 return TCL_ERROR;
00356
00357
00358 return TCL_OK;
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 int cmd_rawtimestep(ClientData cd, Tcl_Interp *interp, int argc,
00372 Tcl_Obj * const objv[]) {
00373 VMDApp *app = (VMDApp *)cd;
00374 Molecule *mol;
00375 Timestep *ts;
00376 int molid=-1, start=0, frame=-1, length, neededLength;
00377 unsigned char *bytes;
00378
00379 if (argc != 3 && argc != 5 && argc != 7) {
00380 Tcl_WrongNumArgs(interp, 1,objv,
00381 "<molid> <bytearray> ?-start index? ?-frame whichframe?");
00382 return TCL_ERROR;
00383 }
00384
00385
00386 if (!strcmp(Tcl_GetStringFromObj(objv[1], NULL), "top"))
00387 molid = app->molecule_top();
00388 else if (Tcl_GetIntFromObj(interp, objv[1], &molid) != TCL_OK)
00389 return TCL_ERROR;
00390 if (!(mol = app->moleculeList->mol_from_id(molid))) {
00391 Tcl_SetResult(interp, "rawtimestep: invalid molid", TCL_STATIC);
00392 return TCL_ERROR;
00393 }
00394
00395
00396 if (!(bytes = Tcl_GetByteArrayFromObj(objv[2], &length))) {
00397 Tcl_SetResult(interp, "rawtimestep: could not read bytearray", TCL_STATIC);
00398 return TCL_ERROR;
00399 }
00400
00401
00402 for (int iarg=3; iarg<argc; iarg += 2) {
00403 const char *opt = Tcl_GetStringFromObj(objv[iarg], NULL);
00404 if (!strcmp(opt, "-start")) {
00405 if (Tcl_GetIntFromObj(interp, objv[iarg+1], &start) != TCL_OK)
00406 return TCL_ERROR;
00407 } else if (!strcmp(opt, "-frame")) {
00408
00409
00410 const char *strframe = Tcl_GetStringFromObj(objv[iarg+1], NULL);
00411 if (!strcmp(strframe, "last")) {
00412
00413
00414 frame = mol->numframes()-1;
00415 } else if (!strcmp(strframe, "current")) {
00416 frame = mol->frame();
00417 } else if (!strcmp(strframe, "append")) {
00418 frame = -1;
00419 } else {
00420 int tmpframe = -1;
00421 if (Tcl_GetIntFromObj(interp, objv[iarg+1], &tmpframe) != TCL_OK)
00422 return TCL_ERROR;
00423 if (tmpframe < 0 || tmpframe >= mol->numframes()) {
00424 Tcl_SetResult(interp, "rawtimestep: invalid frame specified.",
00425 TCL_STATIC);
00426 return TCL_ERROR;
00427 }
00428 frame = tmpframe;
00429 }
00430 } else {
00431 Tcl_SetResult(interp, "rawtimestep: valid options are -frame and -start",
00432 TCL_STATIC);
00433 return TCL_ERROR;
00434 }
00435 }
00436
00437
00438 neededLength = 12*mol->nAtoms;
00439 if (length-start < neededLength) {
00440 Tcl_SetResult(interp, "rawtimestep: not enough bytes!", TCL_STATIC);
00441 return TCL_ERROR;
00442 }
00443
00444
00445 ts = (frame < 0) ? new Timestep(mol->nAtoms)
00446 : mol->get_frame(frame);
00447 if (!ts) {
00448 Tcl_SetResult(interp, "rawtimestep: Unable to find timestep!", TCL_STATIC);
00449 return TCL_ERROR;
00450 }
00451 memcpy(ts->pos, bytes+start, neededLength);
00452 if (frame < 0) {
00453 mol->append_frame(ts);
00454 } else {
00455 mol->force_recalc(DrawMolItem::MOL_REGEN);
00456 }
00457 return TCL_OK;
00458 }
00459
00460
00461
00462
00463 int cmd_gettimestep(ClientData cd, Tcl_Interp *interp, int argc,
00464 Tcl_Obj * const objv[]) {
00465 if (argc != 3) {
00466 Tcl_WrongNumArgs(interp, 1, objv, "molid frame");
00467 return TCL_ERROR;
00468 }
00469
00470 VMDApp *app = (VMDApp *)cd;
00471 int molid = -1;
00472 const char *molidstr = Tcl_GetStringFromObj(objv[1], NULL);
00473 if (!strcmp(molidstr, "top")) {
00474 molid = app->molecule_top();
00475 } else if (Tcl_GetIntFromObj(interp, objv[1], &molid) != TCL_OK) {
00476 return TCL_ERROR;
00477 }
00478
00479 Molecule *mol = app->moleculeList->mol_from_id(molid);
00480 if (!mol) {
00481 Tcl_AppendResult(interp, "Invalid molid: ", molidstr, NULL);
00482 return TCL_ERROR;
00483 }
00484
00485 int frame;
00486 if (Tcl_GetIntFromObj(interp, objv[2], &frame) != TCL_OK)
00487 return TCL_ERROR;
00488
00489 if (frame < 0 || frame >= mol->numframes()) {
00490 Tcl_AppendResult(interp, "Invalid frame for molecule ", molidstr, NULL);
00491 return TCL_ERROR;
00492 }
00493
00494 Timestep *ts = mol->get_frame(frame);
00495 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(
00496 (const unsigned char *)(ts->pos),
00497 3*mol->nAtoms*sizeof(float)));
00498
00499 return TCL_OK;
00500 }
00501