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, "Bad goto parameter '" ,argv[2] ,"'\n", NULL);
00204 Tcl_AppendResult(interp,
00205 "Valid values are a non-negative number, 'start', or 'end'.", NULL);
00206 return TCL_ERROR;
00207 }
00208 app->animation_set_frame(newframe);
00209 } else {
00210 cmd_animate_usage(interp);
00211 return TCL_ERROR;
00212 }
00213 } else if(argc >= 4) {
00214 int bf = 0, ef = (-1), fs = 1, mid = (-1);
00215 const char *fileType = NULL;
00216 const char *fileName = NULL;
00217 int do_action = (-1);
00218 int currarg = 1;
00219 int waitfor = FileSpec::WAIT_BACK;
00220
00221
00222 if(!strupncmp(argv[currarg], "read", CMDLEN)) {
00223 do_action = 0;
00224 } else if(!strupncmp(argv[currarg], "write", CMDLEN)) {
00225 do_action = 1;
00226 waitfor = FileSpec::WAIT_ALL;
00227 } else if(!strupncmp(argv[currarg], "delete", CMDLEN)) {
00228 do_action = 2;
00229 fs = -1;
00230 } else {
00231 cmd_animate_usage(interp);
00232 return TCL_ERROR;
00233 }
00234 currarg++;
00235
00236
00237 if(do_action == 0 || do_action == 1) {
00238 fileType = argv[currarg++];
00239 fileName = argv[currarg++];
00240 }
00241
00242 AtomSel *selection = NULL;
00243 ResizeArray<int> volsets;
00244 mid = app->molecule_top();
00245
00246 while(currarg < argc) {
00247 if(currarg < (argc - 1)) {
00248 if(!strupncmp(argv[currarg], "beg", CMDLEN)) {
00249 bf = atoi(argv[currarg+1]);
00250 currarg += 2;
00251 } else if(!strupncmp(argv[currarg], "end", CMDLEN)) {
00252 ef = atoi(argv[currarg+1]);
00253 currarg += 2;
00254 } else if(!strupncmp(argv[currarg], "skip", CMDLEN)) {
00255 fs = atoi(argv[currarg+1]);
00256 currarg += 2;
00257 } else if(do_action == 2 && argc == 4 && currarg == 2 &&
00258 !strupncmp(argv[currarg], "all", CMDLEN)) {
00259 if (strcmp(argv[currarg+1], "top"))
00260 mid = atoi(argv[currarg+1]);
00261 else
00262 mid = app->molecule_top();
00263 currarg += 2;
00264 } else if ((do_action == 0 || do_action == 1) &&
00265 !strupncmp(argv[currarg], "waitfor", CMDLEN)) {
00266 const char *arg = argv[currarg+1];
00267 if (!strupncmp(arg, "all", CMDLEN))
00268 waitfor = FileSpec::WAIT_ALL;
00269 else
00270 waitfor = atoi(arg);
00271 currarg += 2;
00272 } else if (do_action == 1 &&
00273 !strupncmp(argv[currarg], "sel", CMDLEN)) {
00274
00275 const char *selstr = argv[currarg+1];
00276 if (!(selection = tcl_commands_get_sel(interp, selstr))) {
00277 Tcl_AppendResult(interp, "Invalid atom selection ", selstr, NULL);
00278 return TCL_ERROR;
00279 }
00280 currarg += 2;
00281 } else if (do_action == 1 &&
00282 !strupncmp(argv[currarg], "volsets", CMDLEN)) {
00283
00284 const char *volstr = argv[currarg+1];
00285 int nsets;
00286 const char **setstrs;
00287 if (Tcl_SplitList(interp, volstr, &nsets, &setstrs) != TCL_OK) {
00288 Tcl_AppendResult(interp, "Invalid volset argument: ", volstr, NULL);
00289 return TCL_ERROR;
00290 }
00291 for (int i=0; i<nsets; i++) {
00292 int tmp;
00293 if (Tcl_GetInt(interp, setstrs[i], &tmp) != TCL_OK) {
00294 Tcl_Free((char *)setstrs);
00295 return TCL_ERROR;
00296 }
00297 volsets.append(tmp);
00298 }
00299 Tcl_Free((char *)setstrs);
00300 currarg += 2;
00301 } else
00302 return TCL_ERROR;
00303 } else {
00304
00305 if (strcmp(argv[currarg], "top")) {
00306 mid = atoi(argv[currarg++]);
00307 } else {
00308 mid = app->molecule_top();
00309 currarg++;
00310 }
00311 }
00312 }
00313
00314
00315
00316
00317 if (selection) {
00318 if (mid != selection->molid()) {
00319 Tcl_SetResult(interp, (char *) "ERROR: animate: Molecule in selection must match animation molecule.", TCL_STATIC);
00320 return TCL_ERROR;
00321 }
00322 }
00323
00324
00325 FileSpec spec;
00326 spec.first = bf;
00327 spec.last = ef;
00328 spec.stride = fs;
00329 spec.waitfor = waitfor;
00330 if (do_action == 0) {
00331 int rc = app->molecule_load(mid, fileName, fileType, &spec);
00332 if (rc < 0) return TCL_ERROR;
00333
00334 } else if (do_action == 1) {
00335 spec.selection = selection ? selection->on : NULL;
00336 if (volsets.num()) {
00337
00338 spec.nvolsets = volsets.num();
00339 spec.setids = new int[spec.nvolsets];
00340 for (int i=0; i<spec.nvolsets; i++) spec.setids[i] = volsets[i];
00341 }
00342 int numwritten = app->molecule_savetrajectory(mid, fileName, fileType,
00343 &spec);
00344 if (numwritten < 0) return TCL_ERROR;
00345 Tcl_SetObjResult(interp, Tcl_NewIntObj(numwritten));
00346
00347 } else if (do_action == 2)
00348 app->molecule_deleteframes(mid, bf, ef, fs);
00349
00350 else
00351 return TCL_ERROR;
00352
00353 } else
00354 return TCL_ERROR;
00355
00356
00357 return TCL_OK;
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 int cmd_rawtimestep(ClientData cd, Tcl_Interp *interp, int argc,
00371 Tcl_Obj * const objv[]) {
00372 VMDApp *app = (VMDApp *)cd;
00373 Molecule *mol;
00374 Timestep *ts;
00375 int molid=-1, start=0, frame=-1, length, neededLength;
00376 unsigned char *bytes;
00377
00378 if (argc != 3 && argc != 5 && argc != 7) {
00379 Tcl_WrongNumArgs(interp, 1,objv,
00380 "<molid> <bytearray> ?-start index? ?-frame whichframe?");
00381 return TCL_ERROR;
00382 }
00383
00384
00385 if (!strcmp(Tcl_GetStringFromObj(objv[1], NULL), "top"))
00386 molid = app->molecule_top();
00387 else if (Tcl_GetIntFromObj(interp, objv[1], &molid) != TCL_OK)
00388 return TCL_ERROR;
00389 if (!(mol = app->moleculeList->mol_from_id(molid))) {
00390 Tcl_SetResult(interp, (char *) "rawtimestep: invalid molid", TCL_STATIC);
00391 return TCL_ERROR;
00392 }
00393
00394
00395 if (!(bytes = Tcl_GetByteArrayFromObj(objv[2], &length))) {
00396 Tcl_SetResult(interp, (char *) "rawtimestep: could not read bytearray", TCL_STATIC);
00397 return TCL_ERROR;
00398 }
00399
00400
00401 for (int iarg=3; iarg<argc; iarg += 2) {
00402 const char *opt = Tcl_GetStringFromObj(objv[iarg], NULL);
00403 if (!strcmp(opt, "-start")) {
00404 if (Tcl_GetIntFromObj(interp, objv[iarg+1], &start) != TCL_OK)
00405 return TCL_ERROR;
00406 } else if (!strcmp(opt, "-frame")) {
00407
00408
00409 const char *strframe = Tcl_GetStringFromObj(objv[iarg+1], NULL);
00410 if (!strcmp(strframe, "last")) {
00411
00412
00413 frame = mol->numframes()-1;
00414 } else if (!strcmp(strframe, "current")) {
00415 frame = mol->frame();
00416 } else if (!strcmp(strframe, "append")) {
00417 frame = -1;
00418 } else {
00419 int tmpframe = -1;
00420 if (Tcl_GetIntFromObj(interp, objv[iarg+1], &tmpframe) != TCL_OK)
00421 return TCL_ERROR;
00422 if (tmpframe < 0 || tmpframe >= mol->numframes()) {
00423 Tcl_SetResult(interp, (char *) "rawtimestep: invalid frame specified.",
00424 TCL_STATIC);
00425 return TCL_ERROR;
00426 }
00427 frame = tmpframe;
00428 }
00429 } else {
00430 Tcl_SetResult(interp, (char *) "rawtimestep: valid options are -frame and -start",
00431 TCL_STATIC);
00432 return TCL_ERROR;
00433 }
00434 }
00435
00436
00437 neededLength = 12L*mol->nAtoms;
00438 if (length-start < neededLength) {
00439 Tcl_SetResult(interp, (char *) "rawtimestep: not enough bytes!", TCL_STATIC);
00440 return TCL_ERROR;
00441 }
00442
00443
00444 ts = (frame < 0) ? new Timestep(mol->nAtoms)
00445 : mol->get_frame(frame);
00446 if (!ts) {
00447 Tcl_SetResult(interp, (char *) "rawtimestep: Unable to find timestep!", TCL_STATIC);
00448 return TCL_ERROR;
00449 }
00450 memcpy(ts->pos, bytes+start, neededLength);
00451 if (frame < 0) {
00452 mol->append_frame(ts);
00453 } else {
00454 mol->force_recalc(DrawMolItem::MOL_REGEN);
00455 }
00456 return TCL_OK;
00457 }
00458
00459
00460
00461
00462 int cmd_gettimestep(ClientData cd, Tcl_Interp *interp, int argc,
00463 Tcl_Obj * const objv[]) {
00464 if (argc != 3) {
00465 Tcl_WrongNumArgs(interp, 1, objv, "molid frame");
00466 return TCL_ERROR;
00467 }
00468
00469 VMDApp *app = (VMDApp *)cd;
00470 int molid = -1;
00471 const char *molidstr = Tcl_GetStringFromObj(objv[1], NULL);
00472 if (!strcmp(molidstr, "top")) {
00473 molid = app->molecule_top();
00474 } else if (Tcl_GetIntFromObj(interp, objv[1], &molid) != TCL_OK) {
00475 return TCL_ERROR;
00476 }
00477
00478 Molecule *mol = app->moleculeList->mol_from_id(molid);
00479 if (!mol) {
00480 Tcl_AppendResult(interp, "Invalid molid: ", molidstr, NULL);
00481 return TCL_ERROR;
00482 }
00483
00484 int frame;
00485 if (Tcl_GetIntFromObj(interp, objv[2], &frame) != TCL_OK)
00486 return TCL_ERROR;
00487
00488 if (frame < 0 || frame >= mol->numframes()) {
00489 Tcl_AppendResult(interp, "Invalid frame for molecule ", molidstr, NULL);
00490 return TCL_ERROR;
00491 }
00492
00493 Timestep *ts = mol->get_frame(frame);
00494 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(
00495 (const unsigned char *)(ts->pos),
00496 3L*mol->nAtoms*sizeof(float)));
00497
00498 return TCL_OK;
00499 }
00500