示例#1
0
文件: dcdplugin.c 项目: Almad/pymol
/*
 * 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;
}
示例#2
0
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;
}