/* * Read the header information from a dcd file. * Input: fd - a file struct opened for binary reading. * Output: 0 on success, negative error code on failure. * Side effects: *natoms set to number of atoms per frame * *nsets set to number of frames in dcd file * *istart set to starting timestep of dcd file * *nsavc set to timesteps between dcd saves * *delta set to value of trajectory timestep * *nfixed set to number of fixed atoms * *freeind may be set to heap-allocated space * *reverse set to one if reverse-endian, zero if not. * *charmm set to internal code for handling charmm data. */ static int read_dcdheader(fio_fd fd, int *N, int *NSET, int *ISTART, int *NSAVC, double *DELTA, int *NAMNF, int **FREEINDEXES, float **fixedcoords, int *reverseEndian, int *charmm) { unsigned int input_integer[2]; /* buffer space */ int i, ret_val, rec_scale; union hdrufb_union { char charvalue[84]; /* char buffer used to store header */ int intvalue; } hdrbuf; int NTITLE; int dcdcordmagic; char *corp = (char *) &dcdcordmagic; /* coordinate dcd file magic string 'CORD' */ corp[0] = 'C'; corp[1] = 'O'; corp[2] = 'R'; corp[3] = 'D'; /* First thing in the file should be an 84. * some 64-bit compiles have a 64-bit record length indicator, * so we have to read two ints and check in a more complicated * way. :-( */ ret_val = READ(fd, input_integer, 2*sizeof(unsigned int)); CHECK_FREAD(ret_val, "reading first int from dcd file"); CHECK_FEOF(ret_val, "reading first int from dcd file"); /* Check magic number in file header and determine byte order*/ if ((input_integer[0]+input_integer[1]) == 84) { *reverseEndian=0; rec_scale=RECSCALE64BIT; printf("dcdplugin) detected CHARMM -i8 64-bit DCD file of native endianness\n"); } else if (input_integer[0] == 84 && input_integer[1] == dcdcordmagic) { *reverseEndian=0; rec_scale=RECSCALE32BIT; printf("dcdplugin) detected standard 32-bit DCD file of native endianness\n"); } else { /* now try reverse endian */ swap4_aligned(input_integer, 2); /* will have to unswap magic if 32-bit */ if ((input_integer[0]+input_integer[1]) == 84) { *reverseEndian=1; rec_scale=RECSCALE64BIT; printf("dcdplugin) detected CHARMM -i8 64-bit DCD file of opposite endianness\n"); } else { swap4_aligned(&input_integer[1], 1); /* unswap magic (see above) */ if (input_integer[0] == 84 && input_integer[1] == dcdcordmagic) { *reverseEndian=1; rec_scale=RECSCALE32BIT; printf("dcdplugin) detected standard 32-bit DCD file of opposite endianness\n"); } else { /* not simply reversed endianism or -i8, something rather more evil */ printf("dcdplugin) unrecognized DCD header:\n"); printf("dcdplugin) [0]: %10d [1]: %10d\n", input_integer[0], input_integer[1]); printf("dcdplugin) [0]: 0x%08x [1]: 0x%08x\n", input_integer[0], input_integer[1]); return DCD_BADFORMAT; } } } /* check for magic string, in case of long record markers */ if (rec_scale == RECSCALE64BIT) { ret_val = READ(fd, input_integer, sizeof(unsigned int)); if (input_integer[0] != dcdcordmagic) { printf("dcdplugin) failed to find CORD magic in CHARMM -i8 64-bit DCD file\n"); return DCD_BADFORMAT; } } /* Buffer the entire header for random access */ ret_val = READ(fd, hdrbuf.charvalue, 80); CHECK_FREAD(ret_val, "buffering header"); CHECK_FEOF(ret_val, "buffering header"); /* CHARMm-genereate DCD files set the last integer in the */ /* header, which is unused by X-PLOR, to its version number. */ /* Checking if this is nonzero tells us this is a CHARMm file */ /* and to look for other CHARMm flags. */ if (*((int *) (hdrbuf.charvalue + 76)) != 0) { (*charmm) = DCD_IS_CHARMM; if (*((int *) (hdrbuf.charvalue + 40)) != 0) (*charmm) |= DCD_HAS_EXTRA_BLOCK; if (*((int *) (hdrbuf.charvalue + 44)) == 1) (*charmm) |= DCD_HAS_4DIMS; if (rec_scale == RECSCALE64BIT) (*charmm) |= DCD_HAS_64BIT_REC; } else { (*charmm) = DCD_IS_XPLOR; /* must be an X-PLOR format DCD file */ } if (*charmm & DCD_IS_CHARMM) { /* CHARMM and NAMD versions 2.1b1 and later */ printf("dcdplugin) CHARMM format DCD file (also NAMD 2.1 and later)\n"); } else { /* CHARMM and NAMD versions prior to 2.1b1 */ printf("dcdplugin) X-PLOR format DCD file (also NAMD 2.0 and earlier)\n"); } /* Store the number of sets of coordinates (NSET) */ (*NSET) = *((int *)(hdrbuf.charvalue)); if (*reverseEndian) swap4_unaligned(NSET, 1); /* Store ISTART, the starting timestep */ (*ISTART) = *((int *) (hdrbuf.charvalue + 4)); if (*reverseEndian) swap4_unaligned(ISTART, 1); /* Store NSAVC, the number of timesteps between dcd saves */ (*NSAVC) = *((int *) (hdrbuf.charvalue + 8)); if (*reverseEndian) swap4_unaligned(NSAVC, 1); /* Store NAMNF, the number of fixed atoms */ (*NAMNF) = *((int *) (hdrbuf.charvalue + 32)); if (*reverseEndian) swap4_unaligned(NAMNF, 1); /* Read in the timestep, DELTA */ /* Note: DELTA is stored as a double with X-PLOR but as a float with CHARMm */ if ((*charmm) & DCD_IS_CHARMM) { float ftmp; ftmp = *((float *)(hdrbuf.charvalue+36)); /* is this safe on Alpha? */ if (*reverseEndian) swap4_aligned(&ftmp, 1); *DELTA = (double)ftmp; } else { (*DELTA) = *((double *)(hdrbuf.charvalue + 36)); if (*reverseEndian) swap8_unaligned(DELTA, 1); } /* Get the end size of the first block */ ret_val = READ(fd, input_integer, rec_scale*sizeof(int)); CHECK_FREAD(ret_val, "reading second 84 from dcd file"); CHECK_FEOF(ret_val, "reading second 84 from dcd file"); if (*reverseEndian) swap4_aligned(input_integer, rec_scale); if (rec_scale == RECSCALE64BIT) { if ((input_integer[0]+input_integer[1]) != 84) { return DCD_BADFORMAT; } } else { if (input_integer[0] != 84) { return DCD_BADFORMAT; } } /* Read in the size of the next block */ input_integer[1] = 0; ret_val = READ(fd, input_integer, rec_scale*sizeof(int)); CHECK_FREAD(ret_val, "reading size of title block"); CHECK_FEOF(ret_val, "reading size of title block"); if (*reverseEndian) swap4_aligned(input_integer, rec_scale); if ((((input_integer[0]+input_integer[1])-4) % 80) == 0) { /* Read NTITLE, the number of 80 character title strings there are */ ret_val = READ(fd, &NTITLE, sizeof(int)); CHECK_FREAD(ret_val, "reading NTITLE"); CHECK_FEOF(ret_val, "reading NTITLE"); if (*reverseEndian) swap4_aligned(&NTITLE, 1); for (i=0; i<NTITLE; i++) { fio_fseek(fd, 80, FIO_SEEK_CUR); CHECK_FEOF(ret_val, "reading TITLE"); } /* Get the ending size for this block */ ret_val = READ(fd, input_integer, rec_scale*sizeof(int)); CHECK_FREAD(ret_val, "reading size of title block"); CHECK_FEOF(ret_val, "reading size of title block"); } else { return DCD_BADFORMAT; } /* Read in an integer '4' */ input_integer[1] = 0; ret_val = READ(fd, input_integer, rec_scale*sizeof(int)); CHECK_FREAD(ret_val, "reading a '4'"); CHECK_FEOF(ret_val, "reading a '4'"); if (*reverseEndian) swap4_aligned(input_integer, rec_scale); if ((input_integer[0]+input_integer[1]) != 4) { return DCD_BADFORMAT; } /* Read in the number of atoms */ ret_val = READ(fd, N, sizeof(int)); CHECK_FREAD(ret_val, "reading number of atoms"); CHECK_FEOF(ret_val, "reading number of atoms"); if (*reverseEndian) swap4_aligned(N, 1); /* Read in an integer '4' */ input_integer[1] = 0; ret_val = READ(fd, input_integer, rec_scale*sizeof(int)); CHECK_FREAD(ret_val, "reading a '4'"); CHECK_FEOF(ret_val, "reading a '4'"); if (*reverseEndian) swap4_aligned(input_integer, rec_scale); if ((input_integer[0]+input_integer[1]) != 4) { return DCD_BADFORMAT; } *FREEINDEXES = NULL; *fixedcoords = NULL; if (*NAMNF != 0) { (*FREEINDEXES) = (int *) calloc(((*N)-(*NAMNF)), sizeof(int)); if (*FREEINDEXES == NULL) return DCD_BADMALLOC; *fixedcoords = (float *) calloc((*N)*4 - (*NAMNF), sizeof(float)); if (*fixedcoords == NULL) return DCD_BADMALLOC; /* Read in index array size */ input_integer[1]=0; ret_val = READ(fd, input_integer, rec_scale*sizeof(int)); CHECK_FREAD(ret_val, "reading size of index array"); CHECK_FEOF(ret_val, "reading size of index array"); if (*reverseEndian) swap4_aligned(input_integer, rec_scale); if ((input_integer[0]+input_integer[1]) != ((*N)-(*NAMNF))*4) { return DCD_BADFORMAT; } ret_val = READ(fd, (*FREEINDEXES), ((*N)-(*NAMNF))*sizeof(int)); CHECK_FREAD(ret_val, "reading size of index array"); CHECK_FEOF(ret_val, "reading size of index array"); if (*reverseEndian) swap4_aligned((*FREEINDEXES), ((*N)-(*NAMNF))); input_integer[1]=0; ret_val = READ(fd, input_integer, rec_scale*sizeof(int)); CHECK_FREAD(ret_val, "reading size of index array"); CHECK_FEOF(ret_val, "reading size of index array"); if (*reverseEndian) swap4_aligned(input_integer, rec_scale); if ((input_integer[0]+input_integer[1]) != ((*N)-(*NAMNF))*4) { return DCD_BADFORMAT; } } return DCD_SUCCESS; }
static void *open_uhbd_read(const char *filepath, const char *filetype, int *natoms) { FILE *fd; uhbd_t *uhbd; char inbuf[LINESIZE]; int xsize, ysize, zsize; float orig[3], ra, o[3], s[3]; //xdelta[3], ydelta[3], zdelta[3]; int headersize = 0; // for binary format int doswap = 0; // true if byteswapping needed float scale=0; // scale parameter in binary uhbd files if ((fd = fopen(filepath, "rb")) == NULL) { printf("uhbdplugin) Error opening file.\n"); return NULL; } // check if the first part of file is a binary 160, which would indicate // that this is a binary rather than ascii UHBD file. fread(&headersize, sizeof(int), 1, fd); if (headersize == 160) { printf("uhbdplugin) Detected binary .grd file in native endian\n"); doswap = 0; } else { swap4_unaligned(&headersize, 1); if (headersize == 160) { printf("uhbdplugin) Detected binary .grd file in opposite endian\n"); doswap = 1; } else { headersize = 0; } } if (headersize == 160) { int iparams[8]; float fparams[4]; // we're doing binary // read in the entire header, plus the trailing header size char buf[164]; if (fread(buf, 1, 160, fd) != 160) { fprintf(stderr, "uhbdplugin) Error: incomplete header in .grd file.\n"); fclose(fd); return NULL; } // format of header is 72 character title, followed by: // scale dum2 grdflag, idum2 km one km im jm km h ox oy oz // The first two and last four parameters are floats, the rest ints. memcpy(&scale, buf + 72, sizeof(float)); memcpy(iparams, buf + 72 + 8, 32); memcpy(fparams, buf + 72 + 40, 16); if (doswap) { swap4_unaligned(&scale, 1); swap4_unaligned(iparams, 8); swap4_unaligned(fparams, 4); } xsize = iparams[5]; ysize = iparams[6]; zsize = iparams[7]; ra = fparams[0]; orig[0] = fparams[1]; orig[1] = fparams[2]; orig[2] = fparams[3]; } else { rewind(fd); // Read the header if (uhbdgets(inbuf, LINESIZE, fd, "uhbdplugin) error while skipping header lines\n") == NULL) return NULL; if (uhbdgets(inbuf, LINESIZE, fd, "uhbdplugin) error while skipping header lines\n") == NULL) return NULL; /* get grid dimensions, spacing and origin */ if (uhbdgets(inbuf, LINESIZE, fd, "uhbdplugin) error while getting grid dimensions\n") == NULL) { return NULL; } if (sscanf(inbuf, "%d %d %d %e %e %e %e", &xsize, &ysize, &zsize, &ra, orig, orig+1, orig+2) != 7) { printf("uhbdplugin) Error reading grid dimensions, spacing and origin.\n"); return NULL; } if (uhbdgets(inbuf, LINESIZE, fd, "uhbdplugin) error while skipping header lines\n") == NULL) return NULL; if (uhbdgets(inbuf, LINESIZE, fd, "uhbdplugin) error while skipping header lines\n") == NULL) return NULL; } /* allocate and initialize the uhbd structure */ uhbd = new uhbd_t; uhbd->fd = fd; uhbd->vol = NULL; *natoms = MOLFILE_NUMATOMS_NONE; uhbd->nsets = 1; /* this file contains only one data set */ uhbd->scale = scale; // set by binary files only uhbd->doswap = doswap; uhbd->vol = new molfile_volumetric_t[1]; strcpy(uhbd->vol[0].dataname, headersize ? "UHBD binary Electron Density Map" : "UHBD ascii Electron Density Map"); /* Set the unit cell origin and basis vectors */ for (int i=0; i<3; i++) { uhbd->vol[0].origin[i] = orig[i] + ra; o[i] = uhbd->vol[0].origin[i]; } uhbd->vol[0].xaxis[0] = ra * (xsize-1); uhbd->vol[0].xaxis[1] = 0; uhbd->vol[0].xaxis[2] = 0; uhbd->vol[0].yaxis[0] = 0; uhbd->vol[0].yaxis[1] = ra * (ysize-1); uhbd->vol[0].yaxis[2] = 0; uhbd->vol[0].zaxis[0] = 0; uhbd->vol[0].zaxis[1] = 0; uhbd->vol[0].zaxis[2] = ra * (zsize-1); s[0] = uhbd->vol[0].xaxis[0]; s[1] = uhbd->vol[0].yaxis[1]; s[2] = uhbd->vol[0].zaxis[2]; uhbd->vol[0].xsize = xsize; uhbd->vol[0].ysize = ysize; uhbd->vol[0].zsize = zsize; /* UHBD files contain no color information. */ uhbd->vol[0].has_color = 0; return uhbd; }