Example #1
0
static void *open_dcd_read(const char *path, const char *filetype, 
    int *natoms) {
  dcdhandle *dcd;
  fio_fd fd;
  int rc;
  struct stat stbuf;

  if (!path) return NULL;

  /* See if the file exists, and get its size */
  memset(&stbuf, 0, sizeof(struct stat));
  if (stat(path, &stbuf)) {
    printf("dcdplugin) Could not access file '%s'.\n", path);
    return NULL;
  }

  if (fio_open(path, FIO_READ, &fd) < 0) {
    printf("dcdplugin) Could not open file '%s' for reading.\n", path);
    return NULL;
  }

  dcd = (dcdhandle *)malloc(sizeof(dcdhandle));
  memset(dcd, 0, sizeof(dcdhandle));
  dcd->fd = fd;

  if ((rc = read_dcdheader(dcd->fd, &dcd->natoms, &dcd->nsets, &dcd->istart, 
         &dcd->nsavc, &dcd->delta, &dcd->nfixed, &dcd->freeind, 
         &dcd->fixedcoords, &dcd->reverse, &dcd->charmm))) {
    print_dcderror("read_dcdheader", rc);
    fio_fclose(dcd->fd);
    free(dcd);
    return NULL;
  }

  /*
   * Check that the file is big enough to really hold the number of sets
   * it claims to have.  Then we'll use nsets to keep track of where EOF
   * should be.
   */
  {
    fio_size_t ndims, firstframesize, framesize, extrablocksize;
    fio_size_t trjsize, filesize, curpos;
    int newnsets;

    extrablocksize = dcd->charmm & DCD_HAS_EXTRA_BLOCK ? 48 + 8 : 0;
    ndims = dcd->charmm & DCD_HAS_4DIMS ? 4 : 3;
    firstframesize = (dcd->natoms+2) * ndims * sizeof(float) + extrablocksize;
    framesize = (dcd->natoms-dcd->nfixed+2) * ndims * sizeof(float) 
      + extrablocksize;

    /* 
     * It's safe to use ftell, even though ftell returns a long, because the 
     * header size is < 4GB.
     */

    curpos = fio_ftell(dcd->fd); /* save current offset (end of header) */

#if defined(_MSC_VER) && defined(FASTIO_NATIVEWIN32)
    /* the stat() call is not 64-bit savvy on Windows             */
    /* so we have to use the fastio fseek/ftell routines for this */
    /* until we add a portable filesize routine for this purpose  */
    fio_fseek(dcd->fd, 0, FIO_SEEK_END);       /* seek to end of file */
    filesize = fio_ftell(dcd->fd);
    fio_fseek(dcd->fd, curpos, FIO_SEEK_SET);  /* return to end of header */
#else
    filesize = stbuf.st_size; /* this works ok on Unix machines */
#endif
    trjsize = filesize - curpos - firstframesize;
    if (trjsize < 0) {
      printf("dcdplugin) file '%s' appears to contain no timesteps.\n", path);
      fio_fclose(dcd->fd);
      free(dcd);
      return NULL;
    }

    newnsets = trjsize / framesize + 1;

    if (dcd->nsets > 0 && newnsets != dcd->nsets) {
      printf("dcdplugin) Warning: DCD header claims %d frames, file size indicates there are actually %d frames\n", dcd->nsets, newnsets);
    }

    dcd->nsets = newnsets; 
    dcd->setsread = 0;
  }

  dcd->first = 1;
  dcd->x = (float *)malloc(dcd->natoms * sizeof(float));
  dcd->y = (float *)malloc(dcd->natoms * sizeof(float));
  dcd->z = (float *)malloc(dcd->natoms * sizeof(float));
  if (!dcd->x || !dcd->y || !dcd->z) {
    printf("dcdplugin) Unable to allocate space for %d atoms.\n", dcd->natoms);
    if (dcd->x)
      free(dcd->x);
    if (dcd->y)
      free(dcd->y);
    if (dcd->z)
      free(dcd->z);
    fio_fclose(dcd->fd);
    free(dcd);
    return NULL;
  }
  *natoms = dcd->natoms;
  return dcd;
}
Example #2
0
static PyObject *
__read_dcd_header(PyObject *self, PyObject *args)
{

  /* At this point we assume the file has been checked for existence and opened, and the DCD class
   * contains a reference to the file (which can be used to retrieve the file descriptor)
   */
  PyObject *temp;
  fio_fd fd;
  int rc;
  char *remarks = NULL;
  int len_remarks = 0;
  dcdhandle *dcd = NULL;

  if (! self) {
    /* we were in fact called as a module function, try to retrieve
       a matching object from args */
    if( !PyArg_ParseTuple(args, "O", &self) )
      return NULL;
  } else {
    /* we were obviously called as an object method so args should
       only have the int value. */
    if( !PyArg_ParseTuple(args, "") )
      return NULL;
  }

  // Get the file object from the class
  if (!PyObject_HasAttrString(self, "dcdfile")) {
    // Raise exception
    PyErr_SetString(PyExc_AttributeError, "dcdfile is not an attribute");
    return NULL;
  }

  if ((temp = PyObject_GetAttrString(self, "dcdfile")) == NULL) { // This gives me a New Reference
    // Raise exception
    PyErr_SetString(PyExc_AttributeError, "dcdfile is not an attribute");
    return NULL;
  }

  if (!PyFile_CheckExact(temp)) {
    // Raise exception
    PyErr_SetString(PyExc_TypeError, "dcdfile does not refer to a file object");
    goto error;
  }
  fd = fileno(PyFile_AsFile(temp));
  // No longer need the reference to temp
  Py_DECREF(temp);

  dcd = (dcdhandle *)malloc(sizeof(dcdhandle));
  memset(dcd, 0, sizeof(dcdhandle));
  dcd->fd = fd;

  if ((rc = read_dcdheader(dcd->fd, &dcd->natoms, &dcd->nsets, &dcd->istart,
			   &dcd->nsavc, &dcd->delta, &dcd->nfixed, &dcd->freeind,
			   &dcd->fixedcoords, &dcd->reverse, &dcd->charmm, &remarks, &len_remarks))) {
    // Raise exception
    PyErr_SetString(PyExc_IOError, "Cannot read DCD header");
    goto error;
  }

  /*
   * Check that the file is big enough to really hold all the frames it claims to have
   */
  {
    off_t ndims, firstframesize, framesize, extrablocksize;
    off_t filesize;
    struct stat stbuf;

    extrablocksize = dcd->charmm & DCD_HAS_EXTRA_BLOCK ? 48 + 8 : 0;
    ndims = dcd->charmm & DCD_HAS_4DIMS ? 4 : 3;
    firstframesize = (dcd->natoms+2) * ndims * sizeof(float) + extrablocksize;
    framesize = (dcd->natoms-dcd->nfixed+2) * ndims * sizeof(float)
      + extrablocksize;

    // Get filesize from file descriptor
    memset(&stbuf, 0, sizeof(struct stat));
    if (fstat(dcd->fd, &stbuf)) {
      PyErr_SetString(PyExc_IOError, "Could not stat file");
      goto error;
    }

    // Size of header
    dcd->header_size = fio_ftell(dcd->fd);

    /*
     * It's safe to use ftell, even though ftell returns a long, because the
     * header size is < 4GB.
     */
    filesize = stbuf.st_size - fio_ftell(dcd->fd) - firstframesize;
    if (filesize < 0) {
      PyErr_SetString(PyExc_IOError, "DCD file appears to contain no timesteps");
      goto error;
    }
    dcd->nsets = filesize / framesize + 1;
    dcd->setsread = 0;
  }

  // We are at the first frame
  dcd->first = 1;

  temp = Py_BuildValue("s#", remarks, len_remarks);
  if (temp == NULL) goto error;
  if (PyObject_SetAttrString(self, "remarks", temp) == -1) {
    PyErr_SetString(PyExc_AttributeError, "Could not create attribute remarks");
    goto error;
  }
  Py_DECREF(temp);
  temp = Py_BuildValue("i", dcd->natoms);
  if (temp == NULL) goto error;
  if (PyObject_SetAttrString(self, "n_atoms", temp) == -1) {
    PyErr_SetString(PyExc_AttributeError, "Could not create attribute n_atoms");
    goto error;
  }
  Py_DECREF(temp);
  temp = Py_BuildValue("i", dcd->nsets);
  if (temp == NULL) goto error;
  if (PyObject_SetAttrString(self, "n_frames", temp) == -1) {
    PyErr_SetString(PyExc_AttributeError, "Could not create attribute n_frames");
    goto error;
  }
  Py_DECREF(temp);
  temp = Py_BuildValue("i", dcd->nfixed);
  if (temp == NULL) goto error;
  if (PyObject_SetAttrString(self, "fixed", temp) == -1) {
    PyErr_SetString(PyExc_AttributeError, "Could not create attribute fixed");
    goto error;
  }
  Py_DECREF(temp);
  temp = Py_BuildValue("i", dcd->istart);
  if (temp == NULL) goto error;
  if (PyObject_SetAttrString(self, "start_timestep", temp) == -1) {
    PyErr_SetString(PyExc_AttributeError, "Could not create attribute fixed");
    goto error;
  }
  Py_DECREF(temp);
  temp = Py_BuildValue("i", dcd->nsavc);
  if (temp == NULL) goto error;
  if (PyObject_SetAttrString(self, "skip_timestep", temp) == -1) {
    PyErr_SetString(PyExc_AttributeError, "Could not create attribute fixed");
    goto error;
  }
  Py_DECREF(temp);
  temp = Py_BuildValue("d", dcd->delta);
  if (temp == NULL) goto error;
  if (PyObject_SetAttrString(self, "delta", temp) == -1) {
    PyErr_SetString(PyExc_AttributeError, "Could not create attribute fixed");
    goto error;
  }
  Py_DECREF(temp);

  temp = PyCObject_FromVoidPtr(dcd, NULL);
  if (temp == NULL) goto error;
  if (PyObject_SetAttrString(self, "_dcd_C_ptr", temp) == -1) {
    PyErr_SetString(PyExc_AttributeError, "Could not create attribute _dcd_C_ptr");
    goto error;
  }

  if ((dcd->charmm & DCD_IS_CHARMM) && (dcd->charmm & DCD_HAS_EXTRA_BLOCK)) {
    dcd->with_unitcell = 1;
    temp = Py_True;
  } else {
    temp = Py_False;
  }
  Py_INCREF(temp);
  if (PyObject_SetAttrString(self, "periodic", temp) == -1) {
    PyErr_SetString(PyExc_AttributeError, "Could not create attribute periodic");
    goto error;
  }
  Py_DECREF(temp);

  // For debugging purposes
  temp = PyBuffer_FromMemory(dcd, sizeof(dcdhandle));
  if (temp == NULL) goto error;
  if (PyObject_SetAttrString(self, "_dcd_C_str", temp) == -1) {
    PyErr_SetString(PyExc_AttributeError, "Could not create attribute _dcd_C_str");
    goto error;
  }
  Py_DECREF(temp);

  Py_INCREF(Py_None);
  return Py_None;

 error:
  Py_XDECREF(temp);
  if (dcd != NULL) free(dcd);
  if (remarks != NULL) free(remarks);
  return NULL;
}