00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include "largefiles.h"
00046
00047 #include <stdio.h>
00048 #include <sys/stat.h>
00049 #include <sys/types.h>
00050 #include <stdlib.h>
00051 #include <string.h>
00052 #include <math.h>
00053 #include <time.h>
00054 #include "endianswap.h"
00055 #include "fastio.h"
00056 #include "molfile_plugin.h"
00057
00058 #ifndef M_PI_2
00059 #define M_PI_2 1.57079632679489661922
00060 #endif
00061
00062 #define RECSCALE32BIT 1
00063 #define RECSCALE64BIT 2
00064 #define RECSCALEMAX 2
00065
00066 typedef struct {
00067 fio_fd fd;
00068 int natoms;
00069 int nsets;
00070 int setsread;
00071 int istart;
00072 int nsavc;
00073 double delta;
00074 int nfixed;
00075 float *x, *y, *z;
00076 int *freeind;
00077 float *fixedcoords;
00078 int reverse;
00079 int charmm;
00080 int first;
00081 int with_unitcell;
00082 } dcdhandle;
00083
00084
00085 #define DCD_SUCCESS 0
00086 #define DCD_EOF -1
00087 #define DCD_DNE -2
00088 #define DCD_OPENFAILED -3
00089 #define DCD_BADREAD -4
00090 #define DCD_BADEOF -5
00091 #define DCD_BADFORMAT -6
00092 #define DCD_FILEEXISTS -7
00093 #define DCD_BADMALLOC -8
00094 #define DCD_BADWRITE -9
00095
00096
00097 #define DCD_IS_CHARMM 0x01
00098 #define DCD_HAS_4DIMS 0x02
00099 #define DCD_HAS_EXTRA_BLOCK 0x04
00100 #define DCD_HAS_64BIT_REC 0x08
00101
00102
00103 #define NFILE_POS 8L
00104 #define NSTEP_POS 20L
00105
00106
00107 #define READ(fd, buf, size) fio_fread(((void *) buf), (size), 1, (fd))
00108
00109
00110 #define WRITE(fd, buf, size) fio_fwrite(((void *) buf), (size), 1, (fd))
00111
00112
00113 #define CHECK_FREAD(X, msg) if (X==-1) { return(DCD_BADREAD); }
00114 #define CHECK_FEOF(X, msg) if (X==0) { return(DCD_BADEOF); }
00115
00116
00117
00118 static void print_dcderror(const char *func, int errcode) {
00119 const char *errstr;
00120
00121 switch (errcode) {
00122 case DCD_EOF: errstr = "end of file"; break;
00123 case DCD_DNE: errstr = "file not found"; break;
00124 case DCD_OPENFAILED: errstr = "file open failed"; break;
00125 case DCD_BADREAD: errstr = "error during read"; break;
00126 case DCD_BADEOF: errstr = "premature end of file"; break;
00127 case DCD_BADFORMAT: errstr = "corruption or unrecognized file structure"; break;
00128 case DCD_FILEEXISTS: errstr = "output file already exists"; break;
00129 case DCD_BADMALLOC: errstr = "memory allocation failed"; break;
00130 case DCD_BADWRITE: errstr = "error during write"; break;
00131 case DCD_SUCCESS:
00132 default:
00133 errstr = "no error";
00134 break;
00135 }
00136 printf("dcdplugin) %s: %s\n", func, errstr);
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 static int read_dcdheader(fio_fd fd, int *N, int *NSET, int *ISTART,
00155 int *NSAVC, double *DELTA, int *NAMNF,
00156 int **FREEINDEXES, float **fixedcoords, int *reverseEndian,
00157 int *charmm)
00158 {
00159 unsigned int input_integer[2];
00160 int i, ret_val, rec_scale;
00161 char hdrbuf[84];
00162 int NTITLE;
00163 int dcdcordmagic;
00164 char *corp = (char *) &dcdcordmagic;
00165
00166
00167 corp[0] = 'C';
00168 corp[1] = 'O';
00169 corp[2] = 'R';
00170 corp[3] = 'D';
00171
00172
00173
00174
00175
00176 ret_val = READ(fd, input_integer, 2*sizeof(unsigned int));
00177 CHECK_FREAD(ret_val, "reading first int from dcd file");
00178 CHECK_FEOF(ret_val, "reading first int from dcd file");
00179
00180
00181 if ((input_integer[0]+input_integer[1]) == 84) {
00182 *reverseEndian=0;
00183 rec_scale=RECSCALE64BIT;
00184 printf("dcdplugin) detected CHARMM -i8 64-bit DCD file of native endianness\n");
00185 } else if (input_integer[0] == 84 && input_integer[1] == dcdcordmagic) {
00186 *reverseEndian=0;
00187 rec_scale=RECSCALE32BIT;
00188 printf("dcdplugin) detected standard 32-bit DCD file of native endianness\n");
00189 } else {
00190
00191 swap4_aligned(input_integer, 2);
00192 if ((input_integer[0]+input_integer[1]) == 84) {
00193 *reverseEndian=1;
00194 rec_scale=RECSCALE64BIT;
00195 printf("dcdplugin) detected CHARMM -i8 64-bit DCD file of opposite endianness\n");
00196 } else {
00197 swap4_aligned(&input_integer[1], 1);
00198 if (input_integer[0] == 84 && input_integer[1] == dcdcordmagic) {
00199 *reverseEndian=1;
00200 rec_scale=RECSCALE32BIT;
00201 printf("dcdplugin) detected standard 32-bit DCD file of opposite endianness\n");
00202 } else {
00203
00204 printf("dcdplugin) unrecognized DCD header:\n");
00205 printf("dcdplugin) [0]: %10d [1]: %10d\n", input_integer[0], input_integer[1]);
00206 printf("dcdplugin) [0]: 0x%08x [1]: 0x%08x\n", input_integer[0], input_integer[1]);
00207 return DCD_BADFORMAT;
00208
00209 }
00210 }
00211 }
00212
00213
00214 if (rec_scale == RECSCALE64BIT) {
00215 ret_val = READ(fd, input_integer, sizeof(unsigned int));
00216 if (input_integer[0] != dcdcordmagic) {
00217 printf("dcdplugin) failed to find CORD magic in CHARMM -i8 64-bit DCD file\n");
00218 return DCD_BADFORMAT;
00219 }
00220 }
00221
00222
00223 ret_val = READ(fd, hdrbuf, 80);
00224 CHECK_FREAD(ret_val, "buffering header");
00225 CHECK_FEOF(ret_val, "buffering header");
00226
00227
00228
00229
00230
00231 if (*((int *) (hdrbuf + 76)) != 0) {
00232 (*charmm) = DCD_IS_CHARMM;
00233 if (*((int *) (hdrbuf + 40)) != 0)
00234 (*charmm) |= DCD_HAS_EXTRA_BLOCK;
00235
00236 if (*((int *) (hdrbuf + 44)) == 1)
00237 (*charmm) |= DCD_HAS_4DIMS;
00238
00239 if (rec_scale == RECSCALE64BIT)
00240 (*charmm) |= DCD_HAS_64BIT_REC;
00241
00242 } else {
00243 (*charmm) = 0;
00244 }
00245
00246
00247 (*NSET) = *((int *) (hdrbuf));
00248 if (*reverseEndian) swap4_unaligned(NSET, 1);
00249
00250
00251 (*ISTART) = *((int *) (hdrbuf + 4));
00252 if (*reverseEndian) swap4_unaligned(ISTART, 1);
00253
00254
00255 (*NSAVC) = *((int *) (hdrbuf + 8));
00256 if (*reverseEndian) swap4_unaligned(NSAVC, 1);
00257
00258
00259 (*NAMNF) = *((int *) (hdrbuf + 32));
00260 if (*reverseEndian) swap4_unaligned(NAMNF, 1);
00261
00262
00263
00264 if ((*charmm) & DCD_IS_CHARMM) {
00265 float ftmp;
00266 ftmp = *((float *)(hdrbuf+36));
00267 if (*reverseEndian)
00268 swap4_aligned(&ftmp, 1);
00269
00270 *DELTA = (double)ftmp;
00271 } else {
00272 (*DELTA) = *((double *)(hdrbuf + 36));
00273 if (*reverseEndian) swap8_unaligned(DELTA, 1);
00274 }
00275
00276
00277 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00278 CHECK_FREAD(ret_val, "reading second 84 from dcd file");
00279 CHECK_FEOF(ret_val, "reading second 84 from dcd file");
00280 if (*reverseEndian) swap4_aligned(input_integer, rec_scale);
00281
00282 if (rec_scale == RECSCALE64BIT) {
00283 if ((input_integer[0]+input_integer[1]) != 84) {
00284 return DCD_BADFORMAT;
00285 }
00286 } else {
00287 if (input_integer[0] != 84) {
00288 return DCD_BADFORMAT;
00289 }
00290 }
00291
00292
00293 input_integer[1] = 0;
00294 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00295 CHECK_FREAD(ret_val, "reading size of title block");
00296 CHECK_FEOF(ret_val, "reading size of title block");
00297 if (*reverseEndian) swap4_aligned(input_integer, rec_scale);
00298
00299 if ((((input_integer[0]+input_integer[1])-4) % 80) == 0) {
00300
00301 ret_val = READ(fd, &NTITLE, sizeof(int));
00302 CHECK_FREAD(ret_val, "reading NTITLE");
00303 CHECK_FEOF(ret_val, "reading NTITLE");
00304 if (*reverseEndian) swap4_aligned(&NTITLE, 1);
00305
00306 for (i=0; i<NTITLE; i++) {
00307 fio_fseek(fd, 80, FIO_SEEK_CUR);
00308 CHECK_FEOF(ret_val, "reading TITLE");
00309 }
00310
00311
00312 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00313 CHECK_FREAD(ret_val, "reading size of title block");
00314 CHECK_FEOF(ret_val, "reading size of title block");
00315 } else {
00316 return DCD_BADFORMAT;
00317 }
00318
00319
00320 input_integer[1] = 0;
00321 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00322
00323 CHECK_FREAD(ret_val, "reading a '4'");
00324 CHECK_FEOF(ret_val, "reading a '4'");
00325 if (*reverseEndian) swap4_aligned(input_integer, rec_scale);
00326
00327 if ((input_integer[0]+input_integer[1]) != 4) {
00328 return DCD_BADFORMAT;
00329 }
00330
00331
00332 ret_val = READ(fd, N, sizeof(int));
00333 CHECK_FREAD(ret_val, "reading number of atoms");
00334 CHECK_FEOF(ret_val, "reading number of atoms");
00335 if (*reverseEndian) swap4_aligned(N, 1);
00336
00337
00338 input_integer[1] = 0;
00339 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00340 CHECK_FREAD(ret_val, "reading a '4'");
00341 CHECK_FEOF(ret_val, "reading a '4'");
00342 if (*reverseEndian) swap4_aligned(input_integer, rec_scale);
00343
00344 if ((input_integer[0]+input_integer[1]) != 4) {
00345 return DCD_BADFORMAT;
00346 }
00347
00348 *FREEINDEXES = NULL;
00349 *fixedcoords = NULL;
00350 if (*NAMNF != 0) {
00351 (*FREEINDEXES) = (int *) calloc(((*N)-(*NAMNF)), sizeof(int));
00352 if (*FREEINDEXES == NULL)
00353 return DCD_BADMALLOC;
00354
00355 *fixedcoords = (float *) calloc((*N)*4 - (*NAMNF), sizeof(float));
00356 if (*fixedcoords == NULL)
00357 return DCD_BADMALLOC;
00358
00359
00360 input_integer[1]=0;
00361 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00362 CHECK_FREAD(ret_val, "reading size of index array");
00363 CHECK_FEOF(ret_val, "reading size of index array");
00364 if (*reverseEndian) swap4_aligned(input_integer, rec_scale);
00365
00366 if ((input_integer[0]+input_integer[1]) != ((*N)-(*NAMNF))*4) {
00367 return DCD_BADFORMAT;
00368 }
00369
00370 ret_val = READ(fd, (*FREEINDEXES), ((*N)-(*NAMNF))*sizeof(int));
00371 CHECK_FREAD(ret_val, "reading size of index array");
00372 CHECK_FEOF(ret_val, "reading size of index array");
00373
00374 if (*reverseEndian)
00375 swap4_aligned((*FREEINDEXES), ((*N)-(*NAMNF)));
00376
00377 input_integer[1]=0;
00378 ret_val = READ(fd, input_integer, rec_scale*sizeof(int));
00379 CHECK_FREAD(ret_val, "reading size of index array");
00380 CHECK_FEOF(ret_val, "reading size of index array");
00381 if (*reverseEndian) swap4_aligned(input_integer, rec_scale);
00382
00383 if ((input_integer[0]+input_integer[1]) != ((*N)-(*NAMNF))*4) {
00384 return DCD_BADFORMAT;
00385 }
00386 }
00387
00388 return DCD_SUCCESS;
00389 }
00390
00391 static int read_charmm_extrablock(fio_fd fd, int charmm, int reverseEndian,
00392 float *unitcell) {
00393 int i, input_integer[2], rec_scale;
00394
00395 if (charmm & DCD_HAS_64BIT_REC) {
00396 rec_scale = RECSCALE64BIT;
00397 } else {
00398 rec_scale = RECSCALE32BIT;
00399 }
00400
00401 if ((charmm & DCD_IS_CHARMM) && (charmm & DCD_HAS_EXTRA_BLOCK)) {
00402
00403 input_integer[1] = 0;
00404 if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale)
00405 return DCD_BADREAD;
00406 if (reverseEndian) swap4_aligned(input_integer, rec_scale);
00407 if ((input_integer[0]+input_integer[1]) == 48) {
00408 double tmp[6];
00409 if (fio_fread(tmp, 48, 1, fd) != 1) return DCD_BADREAD;
00410 if (reverseEndian)
00411 swap8_aligned(tmp, 6);
00412 for (i=0; i<6; i++) unitcell[i] = (float)tmp[i];
00413 } else {
00414
00415 if (fio_fseek(fd, (input_integer[0]+input_integer[1]), FIO_SEEK_CUR)) return DCD_BADREAD;
00416 }
00417 if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD;
00418 }
00419
00420 return DCD_SUCCESS;
00421 }
00422
00423 static int read_fixed_atoms(fio_fd fd, int N, int num_free, const int *indexes,
00424 int reverseEndian, const float *fixedcoords,
00425 float *freeatoms, float *pos, int charmm) {
00426 int i, input_integer[2], rec_scale;
00427
00428 if(charmm & DCD_HAS_64BIT_REC) {
00429 rec_scale=RECSCALE64BIT;
00430 } else {
00431 rec_scale=RECSCALE32BIT;
00432 }
00433
00434
00435 input_integer[1]=0;
00436 if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD;
00437 if (reverseEndian) swap4_aligned(input_integer, rec_scale);
00438 if ((input_integer[0]+input_integer[1]) != 4*num_free) return DCD_BADFORMAT;
00439
00440
00441 if (fio_fread(freeatoms, 4*num_free, 1, fd) != 1) return DCD_BADREAD;
00442 if (reverseEndian)
00443 swap4_aligned(freeatoms, num_free);
00444
00445
00446 memcpy(pos, fixedcoords, 4*N);
00447 for (i=0; i<num_free; i++)
00448 pos[indexes[i]-1] = freeatoms[i];
00449
00450
00451 input_integer[1]=0;
00452 if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD;
00453 if (reverseEndian) swap4_aligned(input_integer, rec_scale);
00454 if ((input_integer[0]+input_integer[1]) != 4*num_free) return DCD_BADFORMAT;
00455
00456 return DCD_SUCCESS;
00457 }
00458
00459 static int read_charmm_4dim(fio_fd fd, int charmm, int reverseEndian) {
00460 int input_integer[2],rec_scale;
00461
00462 if (charmm & DCD_HAS_64BIT_REC) {
00463 rec_scale=RECSCALE64BIT;
00464 } else {
00465 rec_scale=RECSCALE32BIT;
00466 }
00467
00468
00469
00470 if ((charmm & DCD_IS_CHARMM) && (charmm & DCD_HAS_4DIMS)) {
00471 input_integer[1]=0;
00472 if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD;
00473 if (reverseEndian) swap4_aligned(input_integer, rec_scale);
00474 if (fio_fseek(fd, (input_integer[0]+input_integer[1]), FIO_SEEK_CUR)) return DCD_BADREAD;
00475 if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD;
00476 }
00477
00478 return DCD_SUCCESS;
00479 }
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 static int read_dcdstep(fio_fd fd, int N, float *X, float *Y, float *Z,
00496 float *unitcell, int num_fixed,
00497 int first, int *indexes, float *fixedcoords,
00498 int reverseEndian, int charmm) {
00499 int ret_val, rec_scale;
00500
00501 if (charmm & DCD_HAS_64BIT_REC) {
00502 rec_scale=RECSCALE64BIT;
00503 } else {
00504 rec_scale=RECSCALE32BIT;
00505 }
00506
00507 if ((num_fixed==0) || first) {
00508
00509
00510 int tmpbuf[6*RECSCALEMAX];
00511
00512 fio_iovec iov[7];
00513 fio_size_t readlen;
00514 int i;
00515
00516
00517
00518
00519
00520
00521
00522
00523 ret_val = read_charmm_extrablock(fd, charmm, reverseEndian, unitcell);
00524 if (ret_val) return ret_val;
00525
00526
00527 iov[0].iov_base = (fio_caddr_t) &tmpbuf[0];
00528 iov[0].iov_len = rec_scale*sizeof(int);
00529
00530 iov[1].iov_base = (fio_caddr_t) X;
00531 iov[1].iov_len = sizeof(float)*N;
00532
00533 iov[2].iov_base = (fio_caddr_t) &tmpbuf[1*rec_scale];
00534 iov[2].iov_len = rec_scale*sizeof(int) * 2;
00535
00536 iov[3].iov_base = (fio_caddr_t) Y;
00537 iov[3].iov_len = sizeof(float)*N;
00538
00539 iov[4].iov_base = (fio_caddr_t) &tmpbuf[3*rec_scale];
00540 iov[4].iov_len = rec_scale*sizeof(int) * 2;
00541
00542 iov[5].iov_base = (fio_caddr_t) Z;
00543 iov[5].iov_len = sizeof(float)*N;
00544
00545 iov[6].iov_base = (fio_caddr_t) &tmpbuf[5*rec_scale];
00546 iov[6].iov_len = rec_scale*sizeof(int);
00547
00548 readlen = fio_readv(fd, &iov[0], 7);
00549
00550 if (readlen != (rec_scale*6*sizeof(int) + 3*N*sizeof(float)))
00551 return DCD_BADREAD;
00552
00553
00554 if (reverseEndian) {
00555 swap4_aligned(&tmpbuf[0], rec_scale*6);
00556 swap4_aligned(X, N);
00557 swap4_aligned(Y, N);
00558 swap4_aligned(Z, N);
00559 }
00560
00561
00562 if(rec_scale == 1) {
00563 for (i=0; i<6; i++) {
00564 if (tmpbuf[i] != sizeof(float)*N) return DCD_BADFORMAT;
00565 }
00566 } else {
00567 for (i=0; i<6; i++) {
00568 if ((tmpbuf[2*i]+tmpbuf[2*i+1]) != sizeof(float)*N) return DCD_BADFORMAT;
00569 }
00570 }
00571
00572
00573
00574 if (num_fixed && first) {
00575 memcpy(fixedcoords, X, N*sizeof(float));
00576 memcpy(fixedcoords+N, Y, N*sizeof(float));
00577 memcpy(fixedcoords+2*N, Z, N*sizeof(float));
00578 }
00579
00580
00581
00582
00583
00584 ret_val = read_charmm_4dim(fd, charmm, reverseEndian);
00585 if (ret_val) return ret_val;
00586 } else {
00587
00588
00589 ret_val = read_charmm_extrablock(fd, charmm, reverseEndian, unitcell);
00590 if (ret_val) return ret_val;
00591 ret_val = read_fixed_atoms(fd, N, N-num_fixed, indexes, reverseEndian,
00592 fixedcoords, fixedcoords+3*N, X, charmm);
00593 if (ret_val) return ret_val;
00594 ret_val = read_fixed_atoms(fd, N, N-num_fixed, indexes, reverseEndian,
00595 fixedcoords+N, fixedcoords+3*N, Y, charmm);
00596 if (ret_val) return ret_val;
00597 ret_val = read_fixed_atoms(fd, N, N-num_fixed, indexes, reverseEndian,
00598 fixedcoords+2*N, fixedcoords+3*N, Z, charmm);
00599 if (ret_val) return ret_val;
00600 ret_val = read_charmm_4dim(fd, charmm, reverseEndian);
00601 if (ret_val) return ret_val;
00602 }
00603
00604 return DCD_SUCCESS;
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619 static int skip_dcdstep(fio_fd fd, int natoms, int nfixed, int charmm) {
00620
00621 int seekoffset = 0;
00622 int rec_scale;
00623
00624 if (charmm & DCD_HAS_64BIT_REC) {
00625 rec_scale=RECSCALE64BIT;
00626 } else {
00627 rec_scale=RECSCALE32BIT;
00628 }
00629
00630
00631 if ((charmm & DCD_IS_CHARMM) && (charmm & DCD_HAS_EXTRA_BLOCK)) {
00632 seekoffset += 4*rec_scale + 48 + 4*rec_scale;
00633 }
00634
00635
00636 seekoffset += 3 * (2*rec_scale + natoms - nfixed) * 4;
00637
00638
00639 if ((charmm & DCD_IS_CHARMM) && (charmm & DCD_HAS_4DIMS)) {
00640 seekoffset += (2*rec_scale + natoms - nfixed) * 4;
00641 }
00642
00643 if (fio_fseek(fd, seekoffset, FIO_SEEK_CUR)) return DCD_BADEOF;
00644
00645 return DCD_SUCCESS;
00646 }
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 static int write_dcdstep(fio_fd fd, int curframe, int curstep, int N,
00660 const float *X, const float *Y, const float *Z,
00661 const double *unitcell, int charmm) {
00662 int out_integer;
00663 int rc;
00664
00665 if (charmm) {
00666
00667 if (unitcell != NULL) {
00668 out_integer = 48;
00669 fio_write_int32(fd, out_integer);
00670 WRITE(fd, unitcell, out_integer);
00671 fio_write_int32(fd, out_integer);
00672 }
00673 }
00674
00675
00676 out_integer = N*4;
00677 fio_write_int32(fd, out_integer);
00678 if (fio_fwrite((void *) X, out_integer, 1, fd) != 1) return DCD_BADWRITE;
00679 fio_write_int32(fd, out_integer);
00680 fio_write_int32(fd, out_integer);
00681 if (fio_fwrite((void *) Y, out_integer, 1, fd) != 1) return DCD_BADWRITE;
00682 fio_write_int32(fd, out_integer);
00683 fio_write_int32(fd, out_integer);
00684 if (fio_fwrite((void *) Z, out_integer, 1, fd) != 1) return DCD_BADWRITE;
00685 fio_write_int32(fd, out_integer);
00686
00687
00688 fio_fseek(fd, NFILE_POS, FIO_SEEK_SET);
00689 fio_write_int32(fd, curframe);
00690 fio_fseek(fd, NSTEP_POS, FIO_SEEK_SET);
00691 fio_write_int32(fd, curstep);
00692 fio_fseek(fd, 0, FIO_SEEK_END);
00693
00694 return DCD_SUCCESS;
00695 }
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706 static int write_dcdheader(fio_fd fd, const char *remarks, int N,
00707 int ISTART, int NSAVC, double DELTA, int with_unitcell,
00708 int charmm) {
00709 int out_integer;
00710 float out_float;
00711 char title_string[200];
00712 time_t cur_time;
00713 struct tm *tmbuf;
00714 char time_str[81];
00715
00716 out_integer = 84;
00717 WRITE(fd, (char *) & out_integer, sizeof(int));
00718 strcpy(title_string, "CORD");
00719 WRITE(fd, title_string, 4);
00720 fio_write_int32(fd, 0);
00721 fio_write_int32(fd, ISTART);
00722 fio_write_int32(fd, NSAVC);
00723 fio_write_int32(fd, 0);
00724 fio_write_int32(fd, 0);
00725 fio_write_int32(fd, 0);
00726 fio_write_int32(fd, 0);
00727 fio_write_int32(fd, 0);
00728 fio_write_int32(fd, 0);
00729 if (charmm) {
00730 out_float = DELTA;
00731 WRITE(fd, (char *) &out_float, sizeof(float));
00732 if (with_unitcell) {
00733 fio_write_int32(fd, 1);
00734 } else {
00735 fio_write_int32(fd, 0);
00736 }
00737 } else {
00738 WRITE(fd, (char *) &DELTA, sizeof(double));
00739 }
00740 fio_write_int32(fd, 0);
00741 fio_write_int32(fd, 0);
00742 fio_write_int32(fd, 0);
00743 fio_write_int32(fd, 0);
00744 fio_write_int32(fd, 0);
00745 fio_write_int32(fd, 0);
00746 fio_write_int32(fd, 0);
00747 fio_write_int32(fd, 0);
00748 if (charmm) {
00749 fio_write_int32(fd, 24);
00750 } else {
00751 fio_write_int32(fd, 0);
00752 }
00753 fio_write_int32(fd, 84);
00754 fio_write_int32(fd, 164);
00755 fio_write_int32(fd, 2);
00756
00757 strncpy(title_string, remarks, 80);
00758 title_string[79] = '\0';
00759 WRITE(fd, title_string, 80);
00760
00761 cur_time=time(NULL);
00762 tmbuf=localtime(&cur_time);
00763 strftime(time_str, 80, "REMARKS Created %d %B, %Y at %R", tmbuf);
00764 WRITE(fd, time_str, 80);
00765
00766 fio_write_int32(fd, 164);
00767 fio_write_int32(fd, 4);
00768 fio_write_int32(fd, N);
00769 fio_write_int32(fd, 4);
00770
00771 return DCD_SUCCESS;
00772 }
00773
00774
00775
00776
00777
00778
00779
00780
00781 static void close_dcd_read(int *indexes, float *fixedcoords) {
00782 free(indexes);
00783 free(fixedcoords);
00784 }
00785
00786
00787
00788
00789
00790 static void *open_dcd_read(const char *path, const char *filetype,
00791 int *natoms) {
00792 dcdhandle *dcd;
00793 fio_fd fd;
00794 int rc;
00795 struct stat stbuf;
00796
00797 if (!path) return NULL;
00798
00799
00800 memset(&stbuf, 0, sizeof(struct stat));
00801 if (stat(path, &stbuf)) {
00802 printf("dcdplugin) Could not access file '%s'.\n", path);
00803 return NULL;
00804 }
00805
00806 if (fio_open(path, FIO_READ, &fd) < 0) {
00807 printf("dcdplugin) Could not open file '%s' for reading.\n", path);
00808 return NULL;
00809 }
00810
00811 dcd = (dcdhandle *)malloc(sizeof(dcdhandle));
00812 memset(dcd, 0, sizeof(dcdhandle));
00813 dcd->fd = fd;
00814
00815 if ((rc = read_dcdheader(dcd->fd, &dcd->natoms, &dcd->nsets, &dcd->istart,
00816 &dcd->nsavc, &dcd->delta, &dcd->nfixed, &dcd->freeind,
00817 &dcd->fixedcoords, &dcd->reverse, &dcd->charmm))) {
00818 print_dcderror("read_dcdheader", rc);
00819 fio_fclose(dcd->fd);
00820 free(dcd);
00821 return NULL;
00822 }
00823
00824
00825
00826
00827
00828
00829 {
00830 fio_size_t ndims, firstframesize, framesize, extrablocksize;
00831 fio_size_t trjsize, filesize, curpos;
00832 int newnsets;
00833
00834 extrablocksize = dcd->charmm & DCD_HAS_EXTRA_BLOCK ? 48 + 8 : 0;
00835 ndims = dcd->charmm & DCD_HAS_4DIMS ? 4 : 3;
00836 firstframesize = (dcd->natoms+2) * ndims * sizeof(float) + extrablocksize;
00837 framesize = (dcd->natoms-dcd->nfixed+2) * ndims * sizeof(float)
00838 + extrablocksize;
00839
00840
00841
00842
00843
00844
00845 curpos = fio_ftell(dcd->fd);
00846
00847 #if defined(_MSC_VER) && defined(FASTIO_NATIVEWIN32)
00848
00849
00850
00851 fio_fseek(dcd->fd, 0, FIO_SEEK_END);
00852 filesize = fio_ftell(dcd->fd);
00853 fio_fseek(dcd->fd, curpos, FIO_SEEK_SET);
00854 #else
00855 filesize = stbuf.st_size;
00856 #endif
00857 trjsize = filesize - curpos - firstframesize;
00858 if (trjsize < 0) {
00859 printf("dcdplugin) file '%s' appears to contain no timesteps.\n", path);
00860 fio_fclose(dcd->fd);
00861 free(dcd);
00862 return NULL;
00863 }
00864
00865 newnsets = trjsize / framesize + 1;
00866
00867 if (dcd->nsets > 0 && newnsets != dcd->nsets) {
00868 printf("dcdplugin) Warning: DCD header claims %d frames, file size indicates there are actually %d frames\n", dcd->nsets, newnsets);
00869 }
00870
00871 dcd->nsets = newnsets;
00872 dcd->setsread = 0;
00873 }
00874
00875 dcd->first = 1;
00876 dcd->x = (float *)malloc(dcd->natoms * sizeof(float));
00877 dcd->y = (float *)malloc(dcd->natoms * sizeof(float));
00878 dcd->z = (float *)malloc(dcd->natoms * sizeof(float));
00879 if (!dcd->x || !dcd->y || !dcd->z) {
00880 printf("dcdplugin) Unable to allocate space for %d atoms.\n", dcd->natoms);
00881 if (dcd->x)
00882 free(dcd->x);
00883 if (dcd->y)
00884 free(dcd->y);
00885 if (dcd->z)
00886 free(dcd->z);
00887 fio_fclose(dcd->fd);
00888 free(dcd);
00889 return NULL;
00890 }
00891 *natoms = dcd->natoms;
00892 return dcd;
00893 }
00894
00895
00896 static int read_next_timestep(void *v, int natoms, molfile_timestep_t *ts) {
00897 dcdhandle *dcd;
00898 int i, j, rc;
00899 float unitcell[6];
00900 unitcell[0] = unitcell[2] = unitcell[5] = 1.0f;
00901 unitcell[1] = unitcell[3] = unitcell[4] = 90.0f;
00902 dcd = (dcdhandle *)v;
00903
00904
00905 if (dcd->setsread == dcd->nsets) return MOLFILE_EOF;
00906 dcd->setsread++;
00907 if (!ts) {
00908 if (dcd->first && dcd->nfixed) {
00909
00910 rc = read_dcdstep(dcd->fd, dcd->natoms, dcd->x, dcd->y, dcd->z,
00911 unitcell, dcd->nfixed, dcd->first, dcd->freeind, dcd->fixedcoords,
00912 dcd->reverse, dcd->charmm);
00913 dcd->first = 0;
00914 return rc;
00915 }
00916 dcd->first = 0;
00917
00918 return skip_dcdstep(dcd->fd, dcd->natoms, dcd->nfixed, dcd->charmm);
00919 }
00920 rc = read_dcdstep(dcd->fd, dcd->natoms, dcd->x, dcd->y, dcd->z, unitcell,
00921 dcd->nfixed, dcd->first, dcd->freeind, dcd->fixedcoords,
00922 dcd->reverse, dcd->charmm);
00923 dcd->first = 0;
00924 if (rc < 0) {
00925 print_dcderror("read_dcdstep", rc);
00926 return MOLFILE_ERROR;
00927 }
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 {
00938 int natoms = dcd->natoms;
00939 float *nts = ts->coords;
00940 const float *bufx = dcd->x;
00941 const float *bufy = dcd->y;
00942 const float *bufz = dcd->z;
00943
00944 for (i=0, j=0; i<natoms; i++, j+=3) {
00945 nts[j ] = bufx[i];
00946 nts[j + 1] = bufy[i];
00947 nts[j + 2] = bufz[i];
00948 }
00949 }
00950
00951 ts->A = unitcell[0];
00952 ts->B = unitcell[2];
00953 ts->C = unitcell[5];
00954
00955 if (unitcell[1] >= -1.0 && unitcell[1] <= 1.0 &&
00956 unitcell[3] >= -1.0 && unitcell[3] <= 1.0 &&
00957 unitcell[4] >= -1.0 && unitcell[4] <= 1.0) {
00958
00959
00960
00961
00962 ts->alpha = 90.0 - asin(unitcell[4]) * 90.0 / M_PI_2;
00963 ts->beta = 90.0 - asin(unitcell[3]) * 90.0 / M_PI_2;
00964 ts->gamma = 90.0 - asin(unitcell[1]) * 90.0 / M_PI_2;
00965 } else {
00966
00967
00968 ts->alpha = unitcell[4];
00969 ts->beta = unitcell[3];
00970 ts->gamma = unitcell[1];
00971 }
00972
00973 return MOLFILE_SUCCESS;
00974 }
00975
00976
00977 static void close_file_read(void *v) {
00978 dcdhandle *dcd = (dcdhandle *)v;
00979 close_dcd_read(dcd->freeind, dcd->fixedcoords);
00980 fio_fclose(dcd->fd);
00981 free(dcd->x);
00982 free(dcd->y);
00983 free(dcd->z);
00984 free(dcd);
00985 }
00986
00987
00988 static void *open_dcd_write(const char *path, const char *filetype,
00989 int natoms) {
00990 dcdhandle *dcd;
00991 fio_fd fd;
00992 int rc;
00993 int istart, nsavc;
00994 double delta;
00995 int with_unitcell;
00996 int charmm;
00997
00998 if (fio_open(path, FIO_WRITE, &fd) < 0) {
00999 printf("dcdplugin) Could not open file '%s' for writing\n", path);
01000 return NULL;
01001 }
01002
01003 dcd = (dcdhandle *)malloc(sizeof(dcdhandle));
01004 memset(dcd, 0, sizeof(dcdhandle));
01005 dcd->fd = fd;
01006
01007 istart = 0;
01008 nsavc = 1;
01009 delta = 1.0;
01010 with_unitcell = 1;
01011 charmm = DCD_IS_CHARMM;
01012 if (with_unitcell)
01013 charmm |= DCD_HAS_EXTRA_BLOCK;
01014
01015 rc = write_dcdheader(dcd->fd, "Created by DCD plugin", natoms,
01016 istart, nsavc, delta, with_unitcell, charmm);
01017
01018 if (rc < 0) {
01019 print_dcderror("write_dcdheader", rc);
01020 fio_fclose(dcd->fd);
01021 free(dcd);
01022 return NULL;
01023 }
01024
01025 dcd->natoms = natoms;
01026 dcd->nsets = 0;
01027 dcd->istart = istart;
01028 dcd->nsavc = nsavc;
01029 dcd->with_unitcell = with_unitcell;
01030 dcd->charmm = charmm;
01031 dcd->x = (float *)malloc(natoms * sizeof(float));
01032 dcd->y = (float *)malloc(natoms * sizeof(float));
01033 dcd->z = (float *)malloc(natoms * sizeof(float));
01034 return dcd;
01035 }
01036
01037
01038 static int write_timestep(void *v, const molfile_timestep_t *ts) {
01039 dcdhandle *dcd = (dcdhandle *)v;
01040 int i, rc, curstep;
01041 float *pos = ts->coords;
01042 double unitcell[6];
01043 unitcell[0] = unitcell[2] = unitcell[5] = 1.0f;
01044 unitcell[1] = unitcell[3] = unitcell[4] = 90.0f;
01045
01046
01047 for (i=0; i<dcd->natoms; i++) {
01048 dcd->x[i] = *(pos++);
01049 dcd->y[i] = *(pos++);
01050 dcd->z[i] = *(pos++);
01051 }
01052 dcd->nsets++;
01053 curstep = dcd->istart + dcd->nsets * dcd->nsavc;
01054
01055 unitcell[0] = ts->A;
01056 unitcell[2] = ts->B;
01057 unitcell[5] = ts->C;
01058 unitcell[1] = sin((M_PI_2 / 90.0) * (90.0 - ts->gamma));
01059 unitcell[3] = sin((M_PI_2 / 90.0) * (90.0 - ts->beta));
01060 unitcell[4] = sin((M_PI_2 / 90.0) * (90.0 - ts->alpha));
01061
01062 rc = write_dcdstep(dcd->fd, dcd->nsets, curstep, dcd->natoms,
01063 dcd->x, dcd->y, dcd->z,
01064 dcd->with_unitcell ? unitcell : NULL,
01065 dcd->charmm);
01066 if (rc < 0) {
01067 print_dcderror("write_dcdstep", rc);
01068 return MOLFILE_ERROR;
01069 }
01070
01071 return MOLFILE_SUCCESS;
01072 }
01073
01074 static void close_file_write(void *v) {
01075 dcdhandle *dcd = (dcdhandle *)v;
01076 fio_fclose(dcd->fd);
01077 free(dcd->x);
01078 free(dcd->y);
01079 free(dcd->z);
01080 free(dcd);
01081 }
01082
01083
01084
01085
01086
01087 static molfile_plugin_t dcdplugin = {
01088 vmdplugin_ABIVERSION,
01089 MOLFILE_PLUGIN_TYPE,
01090 "dcd",
01091 "CHARMM,NAMD,XPLOR DCD Trajectory",
01092 "Justin Gullingsrud, John Stone",
01093 1,
01094 8,
01095 VMDPLUGIN_THREADSAFE,
01096 "dcd",
01097 open_dcd_read,
01098 0,
01099 0,
01100 read_next_timestep,
01101 close_file_read,
01102 open_dcd_write,
01103 0,
01104 write_timestep,
01105 close_file_write
01106 };
01107
01108 VMDPLUGIN_API int VMDPLUGIN_init() {
01109 return VMDPLUGIN_SUCCESS;
01110 }
01111
01112 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
01113 (*cb)(v, (vmdplugin_t *)&dcdplugin);
01114 return VMDPLUGIN_SUCCESS;
01115 }
01116
01117 VMDPLUGIN_API int VMDPLUGIN_fini() {
01118 return VMDPLUGIN_SUCCESS;
01119 }
01120
01121
01122 #ifdef TEST_DCDPLUGIN
01123
01124 #include <sys/time.h>
01125
01126
01127 double time_of_day(void) {
01128 #if defined(_MSC_VER)
01129 double t;
01130
01131 t = GetTickCount();
01132 t = t / 1000.0;
01133
01134 return t;
01135 #else
01136 struct timeval tm;
01137 struct timezone tz;
01138
01139 gettimeofday(&tm, &tz);
01140 return((double)(tm.tv_sec) + (double)(tm.tv_usec)/1000000.0);
01141 #endif
01142 }
01143
01144 int main(int argc, char *argv[]) {
01145 molfile_timestep_t timestep;
01146 void *v;
01147 dcdhandle *dcd;
01148 int i, natoms;
01149 float sizeMB =0.0, totalMB = 0.0;
01150 double starttime, endtime, totaltime = 0.0;
01151
01152 while (--argc) {
01153 ++argv;
01154 natoms = 0;
01155 v = open_dcd_read(*argv, "dcd", &natoms);
01156 if (!v) {
01157 fprintf(stderr, "main) open_dcd_read failed for file %s\n", *argv);
01158 return 1;
01159 }
01160 dcd = (dcdhandle *)v;
01161 sizeMB = ((natoms * 3.0) * dcd->nsets * 4.0) / (1024.0 * 1024.0);
01162 totalMB += sizeMB;
01163 printf("main) file: %s\n", *argv);
01164 printf(" %d atoms, %d frames, size: %6.1fMB\n", natoms, dcd->nsets, sizeMB);
01165
01166 starttime = time_of_day();
01167 timestep.coords = (float *)malloc(3*sizeof(float)*natoms);
01168 for (i=0; i<dcd->nsets; i++) {
01169 int rc = read_next_timestep(v, natoms, ×tep);
01170 if (rc) {
01171 fprintf(stderr, "error in read_next_timestep on frame %d\n", i);
01172 return 1;
01173 }
01174 }
01175 endtime = time_of_day();
01176 close_file_read(v);
01177 totaltime += endtime - starttime;
01178 printf(" Time: %5.1f seconds\n", endtime - starttime);
01179 printf(" Speed: %5.1f MB/sec, %5.1f timesteps/sec\n", sizeMB / (endtime - starttime), (dcd->nsets / (endtime - starttime)));
01180 }
01181 printf("Overall Size: %6.1f MB\n", totalMB);
01182 printf("Overall Time: %6.1f seconds\n", totaltime);
01183 printf("Overall Speed: %5.1f MB/sec\n", totalMB / totaltime);
01184 return 0;
01185 }
01186
01187 #endif
01188