00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "largefiles.h"
00019
00020 #include <math.h>
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <ctype.h>
00025 #include "Gromacs.h"
00026 #include "molfile_plugin.h"
00027
00028 #if defined(_AIX)
00029 #include <strings.h>
00030 #endif
00031
00032 #ifndef M_PI
00033 #define M_PI 3.14159265358979323846
00034 #endif
00035
00036 #if defined(WIN32) || defined(WIN64)
00037 #define strcasecmp stricmp
00038 #endif
00039
00040 typedef struct {
00041 md_file *mf;
00042 int natoms;
00043 int step;
00044 } gmxdata;
00045
00046 static void *open_gro_read(const char *filename, const char *,
00047 int *natoms) {
00048
00049 md_file *mf;
00050 md_header mdh;
00051 gmxdata *gmx;
00052
00053 mf = mdio_open(filename, MDFMT_GRO);
00054 if (!mf) {
00055 fprintf(stderr, "Cannot open file '%s', %s\n",
00056 filename, mdio_errmsg(mdio_errno()));
00057 return NULL;
00058 }
00059
00060
00061 if (gro_header(mf, mdh.title, MAX_MDIO_TITLE,
00062 &mdh.timeval, &mdh.natoms, 0) < 0) {
00063 fprintf(stderr, "Cannot read header fromm '%s', %s\n",
00064 filename, mdio_errmsg(mdio_errno()));
00065
00066 return NULL;
00067 }
00068 *natoms = mdh.natoms;
00069 gmx = new gmxdata;
00070 gmx->mf = mf;
00071 gmx->natoms = mdh.natoms;
00072 return gmx;
00073 }
00074
00075 static int read_gro_structure(void *mydata, int *optflags,
00076 molfile_atom_t *atoms) {
00077
00078 md_atom ma;
00079 char buf[MAX_GRO_LINE + 1];
00080 gmxdata *gmx = (gmxdata *)mydata;
00081
00082 *optflags = MOLFILE_NOOPTIONS;
00083
00084
00085 for (int i = 0; i < gmx->natoms; i++) {
00086 molfile_atom_t *atom = atoms+i;
00087 if (gro_rec(gmx->mf, &ma) < 0) {
00088 fprintf(stderr, "Error reading atom %d from file, %s\n", i+1,
00089 mdio_errmsg(mdio_errno()));
00090 return MOLFILE_ERROR;
00091 }
00092 strcpy(atom->name, ma.atomname);
00093 strcpy(atom->type, ma.atomname);
00094 strcpy(atom->resname, ma.resname);
00095 atom->resid = atoi(ma.resid);
00096 atom->chain[0] = '\0';
00097 atom->segid[0] = '\0';
00098 }
00099
00100 if (mdio_readline(gmx->mf, buf, MAX_GRO_LINE + 1, 0) < 0) {
00101 fprintf(stderr, "Warning, error reading box, %s\n",
00102 mdio_errmsg(mdio_errno()));
00103 }
00104
00105 rewind(gmx->mf->f);
00106 return MOLFILE_SUCCESS;
00107 }
00108
00109 static int read_gro_timestep(void *v, int natoms, molfile_timestep_t *ts) {
00110 gmxdata *gmx = (gmxdata *)v;
00111 md_ts mdts;
00112 memset(&mdts, 0, sizeof(md_ts));
00113 mdts.natoms = natoms;
00114
00115 if (mdio_timestep(gmx->mf, &mdts) < 0)
00116 return MOLFILE_ERROR;
00117 if (ts) {
00118 memcpy(ts->coords, mdts.pos, 3 * sizeof(float) * gmx->natoms);
00119 if (mdts.box) {
00120 ts->A = mdts.box->A;
00121 ts->B = mdts.box->B;
00122 ts->C = mdts.box->C;
00123 ts->alpha = mdts.box->alpha;
00124 ts->beta = mdts.box->beta;
00125 ts->gamma = mdts.box->gamma;
00126 }
00127 }
00128 mdio_tsfree(&mdts);
00129 return MOLFILE_SUCCESS;
00130 }
00131
00132 static void close_gro_read(void *v) {
00133 gmxdata *gmx = (gmxdata *)v;
00134 mdio_close(gmx->mf);
00135 delete gmx;
00136 }
00137
00138 static void *open_g96_read(const char *filename, const char *,
00139 int *natoms) {
00140
00141 md_file *mf;
00142 md_header mdh;
00143 char gbuf[MAX_G96_LINE + 1];
00144
00145 mf = mdio_open(filename, MDFMT_G96);
00146 if (!mf) {
00147 fprintf(stderr, "Cannot open file '%s', %s\n",
00148 filename, mdio_errmsg(mdio_errno()));
00149 return NULL;
00150 }
00151
00152
00153 if (g96_header(mf, mdh.title, MAX_MDIO_TITLE, &mdh.timeval) < 0) {
00154 fprintf(stderr, "Cannot read header from '%s', %s\n",
00155 filename, mdio_errmsg(mdio_errno()));
00156 return NULL;
00157 }
00158
00159
00160 if (mdio_readline(mf, gbuf, MAX_G96_LINE + 1) < 0) {
00161 fprintf(stderr, "Cannot read header from '%s', %s\n",
00162 filename, mdio_errmsg(mdio_errno()));
00163 return NULL;
00164 }
00165 if (!strcasecmp(gbuf, "TIMESTEP")) {
00166
00167 if (mdio_readline(mf, gbuf, MAX_G96_LINE + 1) < 0 ||
00168 mdio_readline(mf, gbuf, MAX_G96_LINE + 1) < 0 ||
00169 mdio_readline(mf, gbuf, MAX_G96_LINE + 1) < 0) {
00170 fprintf(stderr, "Cannot read header from '%s', %s\n",
00171 filename, mdio_errmsg(mdio_errno()));
00172 return NULL;
00173 }
00174 }
00175 if (strcasecmp(gbuf, "POSITION") && strcasecmp(gbuf, "REFPOSITION")) {
00176 fprintf(stderr, "No structure information in file %s\n", filename);
00177 return NULL;
00178 }
00179 *natoms = g96_countatoms(mf);
00180
00181 gmxdata *gmx = new gmxdata;
00182 gmx->mf = mf;
00183 gmx->natoms = *natoms;
00184 return gmx;
00185 }
00186
00187 static int read_g96_structure(void *mydata, int *optflags,
00188 molfile_atom_t *atoms) {
00189
00190 char gbuf[MAX_G96_LINE + 1];
00191 gmxdata *gmx = (gmxdata *)mydata;
00192 md_atom ma;
00193 md_file *mf = gmx->mf;
00194
00195 *optflags = MOLFILE_NOOPTIONS;
00196
00197 for (int i = 0; i < gmx->natoms; i++) {
00198 molfile_atom_t *atom = atoms+i;
00199 if (g96_rec(mf, &ma) < 0) {
00200 fprintf(stderr, "Error reading atom %d from file, %s\n",
00201 i+1, mdio_errmsg(mdio_errno()));
00202 return MOLFILE_ERROR;
00203 }
00204 strcpy(atom->name, ma.atomname);
00205 strcpy(atom->type, ma.atomname);
00206 strcpy(atom->resname, ma.resname);
00207 atom->resid = atoi(ma.resid);
00208 atom->chain[0] = '\0';
00209 atom->segid[0] = '\0';
00210 }
00211
00212 if (mdio_readline(mf, gbuf, MAX_G96_LINE + 1) < 0) {
00213 fprintf(stderr, "Warning, error reading END record, %s\n",
00214 mdio_errmsg(mdio_errno()));
00215 }
00216
00217
00218
00219
00220
00221
00222
00223 long fpos = ftell(mf->f);
00224
00225
00226 if (mdio_readline(mf, gbuf, MAX_G96_LINE + 1) >= 0) {
00227
00228
00229 if (!strcasecmp(gbuf, "VELOCITY") || !strcasecmp(gbuf, "VELOCITYRED")) {
00230
00231 for (;;) {
00232 if (mdio_readline(mf, gbuf, MAX_G96_LINE + 1) < 0)
00233 return MOLFILE_ERROR;
00234 if (!strcasecmp(gbuf, "END")) break;
00235 }
00236
00237
00238
00239 fpos = ftell(mf->f);
00240
00241
00242 if (mdio_readline(mf, gbuf, MAX_G96_LINE + 1) < 0)
00243 return MOLFILE_ERROR;
00244 }
00245
00246
00247 if (!strcasecmp(gbuf, "BOX")) {
00248
00249 if (mdio_readline(mf, gbuf, MAX_G96_LINE + 1) < 0)
00250 return MOLFILE_ERROR;
00251 if (mdio_readline(mf, gbuf, MAX_G96_LINE + 1) < 0)
00252 return MOLFILE_ERROR;
00253 if (strcasecmp(gbuf, "END"))
00254 return MOLFILE_ERROR;
00255 }
00256 else {
00257
00258
00259
00260
00261 fseek(mf->f, fpos, SEEK_SET);
00262 }
00263 }
00264 else {
00265
00266 fseek(mf->f, fpos, SEEK_SET);
00267 }
00268 rewind(mf->f);
00269 return MOLFILE_SUCCESS;
00270 }
00271
00272 static int read_g96_timestep(void *v, int natoms, molfile_timestep_t *ts) {
00273
00274 gmxdata *gmx = (gmxdata *)v;
00275 md_ts mdts;
00276 memset(&mdts, 0, sizeof(md_ts));
00277 mdts.natoms = natoms;
00278
00279 if (mdio_timestep(gmx->mf, &mdts) < 0)
00280 return MOLFILE_ERROR;
00281 if (ts) {
00282 memcpy(ts->coords, mdts.pos, 3 * sizeof(float) * gmx->natoms);
00283 if (mdts.box) {
00284 ts->A = mdts.box->A;
00285 ts->B = mdts.box->B;
00286 ts->C = mdts.box->C;
00287 ts->alpha = mdts.box->alpha;
00288 ts->beta = mdts.box->beta;
00289 ts->gamma = mdts.box->gamma;
00290 }
00291 }
00292 mdio_tsfree(&mdts);
00293 return MOLFILE_SUCCESS;
00294 }
00295
00296 static void close_g96_read(void *v) {
00297 gmxdata *gmx = (gmxdata *)v;
00298 mdio_close(gmx->mf);
00299 delete gmx;
00300 }
00301
00302
00303
00304
00305
00306
00307 static void *open_trr_read(const char *filename, const char *filetype,
00308 int *natoms) {
00309
00310 md_file *mf;
00311 md_header mdh;
00312 gmxdata *gmx;
00313 int format;
00314
00315 if (!strcmp(filetype, "trr"))
00316 format = MDFMT_TRR;
00317 else if (!strcmp(filetype, "xtc"))
00318 format = MDFMT_XTC;
00319 else
00320 return NULL;
00321
00322 mf = mdio_open(filename, format);
00323 if (!mf) {
00324 fprintf(stderr, "Cannot open file '%s', %s\n",
00325 filename, mdio_errmsg(mdio_errno()));
00326 return NULL;
00327 }
00328 if (mdio_header(mf, &mdh) < 0) {
00329 mdio_close(mf);
00330 fprintf(stderr, "Cannot read header fromm '%s', %s\n",
00331 filename, mdio_errmsg(mdio_errno()));
00332 return NULL;
00333 }
00334 *natoms = mdh.natoms;
00335 gmx = new gmxdata;
00336 gmx->mf = mf;
00337 gmx->natoms = mdh.natoms;
00338 return gmx;
00339 }
00340
00341 static int read_trr_timestep(void *v, int natoms, molfile_timestep_t *ts) {
00342 gmxdata *gmx = (gmxdata *)v;
00343 md_ts mdts;
00344 memset(&mdts, 0, sizeof(md_ts));
00345 mdts.natoms = natoms;
00346
00347 if (mdio_timestep(gmx->mf, &mdts) < 0) {
00348 if (mdio_errno() == MDIO_EOF || mdio_errno() == MDIO_IOERROR) {
00349
00350 return MOLFILE_ERROR;
00351 }
00352 fprintf(stderr, "Error reading timestep, %s\n", mdio_errmsg(mdio_errno()));
00353 return MOLFILE_ERROR;
00354 }
00355 if (mdts.natoms != natoms) {
00356 fprintf(stderr, "Timestep in file contains wrong number of atoms\n");
00357 fprintf(stderr, "Found %d, expected %d\n", mdts.natoms, natoms);
00358 mdio_tsfree(&mdts);
00359 return MOLFILE_ERROR;
00360 }
00361
00362 if (ts) {
00363 memcpy(ts->coords, mdts.pos, 3 * sizeof(float) * gmx->natoms);
00364 if (mdts.box) {
00365 ts->A = mdts.box->A;
00366 ts->B = mdts.box->B;
00367 ts->C = mdts.box->C;
00368 ts->alpha = mdts.box->alpha;
00369 ts->beta = mdts.box->beta;
00370 ts->gamma = mdts.box->gamma;
00371 }
00372 }
00373 mdio_tsfree(&mdts);
00374 return MOLFILE_SUCCESS;
00375 }
00376
00377 static void close_trr_read(void *v) {
00378 gmxdata *gmx = (gmxdata *)v;
00379 mdio_close(gmx->mf);
00380 delete gmx;
00381 }
00382
00383
00384 static void *open_trr_write(const char *filename, const char *filetype,
00385 int natoms) {
00386
00387 md_file *mf;
00388 gmxdata *gmx;
00389 int format;
00390
00391 if (!strcmp(filetype, "trr"))
00392 format = MDFMT_TRR;
00393 else if (!strcmp(filetype, "xtc"))
00394 format = MDFMT_XTC;
00395 else
00396 return NULL;
00397
00398 mf = mdio_open(filename, format, MDIO_WRITE);
00399 if (!mf) {
00400 fprintf(stderr, "Cannot open file '%s', %s\n",
00401 filename, mdio_errmsg(mdio_errno()));
00402 return NULL;
00403 }
00404 gmx = new gmxdata;
00405 gmx->mf = mf;
00406 gmx->natoms = natoms;
00407
00408
00409 gmx->step = 0;
00410 gmx->mf->rev = host_is_little_endian();
00411 gmx->mf->prec = sizeof(float);
00412 return gmx;
00413 }
00414
00415
00416 static int write_trr_timestep(void *mydata, const molfile_timestep_t *ts)
00417 {
00418 const float nm=0.1;
00419
00420 gmxdata *gmx = (gmxdata *)mydata;
00421
00422
00423
00424 if (gmx->mf->fmt == MDFMT_TRR) {
00425 int i;
00426
00427 if ( put_trx_int(gmx->mf, TRX_MAGIC)
00428 || put_trx_string(gmx->mf, "GMX_trn_file")
00429 || put_trx_int(gmx->mf, 0)
00430 || put_trx_int(gmx->mf, 0)
00431 || put_trx_int(gmx->mf, 9*sizeof(float))
00432 || put_trx_int(gmx->mf, 0)
00433 || put_trx_int(gmx->mf, 0)
00434 || put_trx_int(gmx->mf, 0)
00435 || put_trx_int(gmx->mf, 0)
00436 || put_trx_int(gmx->mf, 3*sizeof(float)*gmx->natoms)
00437 || put_trx_int(gmx->mf, 0)
00438 || put_trx_int(gmx->mf, 0)
00439 || put_trx_int(gmx->mf, gmx->natoms)
00440 || put_trx_int(gmx->mf, gmx->step)
00441 || put_trx_int(gmx->mf, 0)
00442 || put_trx_real(gmx->mf, 0.1*gmx->step)
00443 || put_trx_real(gmx->mf, 0.0))
00444 return MOLFILE_ERROR;
00445
00446
00447
00448
00449 const float sa = sin((double)ts->alpha/180.0*M_PI);
00450 const float ca = cos((double)ts->alpha/180.0*M_PI);
00451 const float cb = cos((double)ts->beta/180.0*M_PI);
00452 const float cg = cos((double)ts->gamma/180.0*M_PI);
00453 const float sg = sin((double)ts->gamma/180.0*M_PI);
00454 float box[9];
00455 box[0] = ts->A; box[1] = 0.0; box[2] = 0.0;
00456 box[3] = ts->B*ca; box[4] = ts->B*sa; box[5] = 0.0;
00457 box[6] = ts->C*cb; box[7] = ts->C*(ca - cb*cg)/sg;
00458 box[8] = ts->C*sqrt((double)(1.0 + 2.0*ca*cb*cg
00459 - ca*ca - cb*cb - cg*cg)/(1.0 - cg*cg));
00460
00461 for (i=0; i<9; ++i) {
00462 if (put_trx_real(gmx->mf, box[i]*nm))
00463 return MOLFILE_ERROR;
00464 }
00465 #ifdef TEST_TRR_PLUGIN
00466 fprintf(stderr, "box is:\n %f %f %f\n %f %f %f\n %f %f %f\n\n",
00467 box[0], box[1], box[2], box[3], box[4], box[5], box[6], box[7], box[8]);
00468 #endif
00469
00470
00471 for (i=0; i<(3*gmx->natoms); ++i) {
00472 if (put_trx_real(gmx->mf, ts->coords[i]*nm))
00473 return MOLFILE_ERROR;
00474 }
00475 } else {
00476 fprintf(stderr, "only .trr is supported for writing\n");
00477 return MOLFILE_ERROR;
00478 }
00479
00480 ++ gmx->step;
00481 return MOLFILE_SUCCESS;
00482 }
00483
00484
00485 static void close_trr_write(void *v) {
00486 gmxdata *gmx = (gmxdata *)v;
00487 mdio_close(gmx->mf);
00488 delete gmx;
00489 }
00490
00491 #define GROMACS_PLUGIN_MAJOR_VERSION 0
00492 #define GROMACS_PLUGIN_MINOR_VERSION 8
00493
00494
00495
00496
00497 static molfile_plugin_t gro_plugin = {
00498 vmdplugin_ABIVERSION,
00499 MOLFILE_PLUGIN_TYPE,
00500 "gro",
00501 "Gromacs GRO",
00502 "David Norris, Justin Gullingsrud",
00503 GROMACS_PLUGIN_MAJOR_VERSION,
00504 GROMACS_PLUGIN_MINOR_VERSION,
00505 VMDPLUGIN_THREADUNSAFE,
00506 "gro",
00507 open_gro_read,
00508 read_gro_structure,
00509 0,
00510 read_gro_timestep,
00511 close_gro_read,
00512 0,
00513 0,
00514 0,
00515 0,
00516 0,
00517 0,
00518 0
00519 };
00520
00521 static molfile_plugin_t g96_plugin = {
00522 vmdplugin_ABIVERSION,
00523 MOLFILE_PLUGIN_TYPE,
00524 "g96",
00525 "Gromacs g96",
00526 "David Norris, Justin Gullingsrud",
00527 GROMACS_PLUGIN_MAJOR_VERSION,
00528 GROMACS_PLUGIN_MINOR_VERSION,
00529 VMDPLUGIN_THREADUNSAFE,
00530 "g96",
00531 open_g96_read,
00532 read_g96_structure,
00533 0,
00534 read_g96_timestep,
00535 close_g96_read,
00536 0,
00537 0,
00538 0,
00539 0,
00540 0,
00541 0,
00542 0
00543 };
00544
00545 static molfile_plugin_t trr_plugin = {
00546 vmdplugin_ABIVERSION,
00547 MOLFILE_PLUGIN_TYPE,
00548 "trr",
00549 "Gromacs TRR Trajectory",
00550 "David Norris, Justin Gullingsrud, Axel Kohlmeyer",
00551 GROMACS_PLUGIN_MAJOR_VERSION,
00552 GROMACS_PLUGIN_MINOR_VERSION,
00553 VMDPLUGIN_THREADUNSAFE,
00554 "trr",
00555 open_trr_read,
00556 0,
00557 0,
00558 read_trr_timestep,
00559 close_trr_read,
00560 open_trr_write,
00561 0,
00562 write_trr_timestep,
00563 close_trr_write,
00564 0,
00565 0,
00566 0
00567 };
00568
00569 static molfile_plugin_t xtc_plugin = {
00570 vmdplugin_ABIVERSION,
00571 MOLFILE_PLUGIN_TYPE,
00572 "xtc",
00573 "Gromacs XTC Compressed Trajectory",
00574 "David Norris, Justin Gullingsrud",
00575 GROMACS_PLUGIN_MAJOR_VERSION,
00576 GROMACS_PLUGIN_MINOR_VERSION,
00577 VMDPLUGIN_THREADUNSAFE,
00578 "xtc",
00579 open_trr_read,
00580 0,
00581 0,
00582 read_trr_timestep,
00583 close_trr_read,
00584 0,
00585 0,
00586 0,
00587 0,
00588 0,
00589 0,
00590 0
00591 };
00592
00593 VMDPLUGIN_API int VMDPLUGIN_init() {
00594 return 0;
00595 }
00596
00597 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00598 (*cb)(v, (vmdplugin_t *)&gro_plugin);
00599 (*cb)(v, (vmdplugin_t *)&g96_plugin);
00600 (*cb)(v, (vmdplugin_t *)&trr_plugin);
00601 (*cb)(v, (vmdplugin_t *)&xtc_plugin);
00602 return 0;
00603 }
00604
00605 VMDPLUGIN_API int VMDPLUGIN_fini() {
00606 return 0;
00607 }
00608
00609
00610 #ifdef TEST_G96_PLUGIN
00611
00612 int main(int argc, char *argv[]) {
00613 int natoms;
00614
00615 molfile_timestep_t timestep;
00616 void *v;
00617 int i;
00618
00619 if (argc < 2) return 1;
00620 while (--argc) {
00621 ++argv;
00622 v = open_g96_read(*argv, "g96", &natoms);
00623 if (!v) {
00624 fprintf(stderr, "open_g96_read failed for file %s\n", *argv);
00625 return 1;
00626 }
00627 timestep.coords = (float *)malloc(3*sizeof(float)*natoms);
00628 i = 0;
00629 while(!read_g96_timestep(v, natoms, ×tep)) {
00630 ++i;
00631 }
00632 fprintf(stderr, "ended read_g96_timestep on step %d\n", i);
00633 free(timestep.coords);
00634 close_g96_read(v);
00635 }
00636 return 0;
00637 }
00638
00639 #endif
00640
00641 #ifdef TEST_TRR_PLUGIN
00642
00643 int main(int argc, char *argv[]) {
00644 int natoms;
00645
00646 molfile_timestep_t timestep;
00647 void *v, *w;
00648 int i;
00649
00650 if (argc != 3) return 1;
00651 v = open_trr_read(argv[1], "trr", &natoms);
00652 if (!v) {
00653 fprintf(stderr, "open_trr_read failed for file %s\n", argv[1]);
00654 return 1;
00655 }
00656 timestep.coords = (float *)malloc(3*sizeof(float)*natoms);
00657 w = open_trr_write(argv[2], "trr", natoms);
00658 if (!w) {
00659 fprintf(stderr, "open_trr_write failed for file %s\n", argv[2]);
00660 return 1;
00661 }
00662
00663 i = 0;
00664 while(!read_trr_timestep(v, natoms, ×tep)) {
00665 ++i;
00666 if (write_trr_timestep(w, ×tep)) {
00667 fprintf(stderr, "write error\n");
00668 return 1;
00669 }
00670 }
00671
00672 fprintf(stderr, "ended read_trr_timestep on step %d\n", i);
00673 free(timestep.coords);
00674 close_trr_read(v);
00675 close_trr_write(w);
00676 return 0;
00677 }
00678
00679 #endif
00680