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; }
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; }