static void close_js_write(void *v) { jshandle *js = (jshandle *)v; /* update the trajectory header information */ fio_fseek(js->fd, JSNFRAMESOFFSET, FIO_SEEK_SET); fio_write_int32(js->fd, js->nframes); fio_fseek(js->fd, 0, FIO_SEEK_END); fio_fclose(js->fd); #if JSMAJORVERSION > 1 if (js->bondfrom) free(js->bondfrom); if (js->bondto) free(js->bondto); if (js->bondorders) free(js->bondorders); if (js->angles) free(js->angles); if (js->dihedrals) free(js->dihedrals); if (js->impropers) free(js->impropers); if (js->cterms) free(js->cterms); #endif free(js); }
/* * Skip past a timestep. If there are fixed atoms, this cannot be used with * the first timestep. * Input: fd - a file struct from which the header has already been read * natoms - number of atoms per timestep * nfixed - number of fixed atoms * charmm - charmm flags as returned by read_dcdheader * Output: 0 on success, negative error code on failure. * Side effects: One timestep will be skipped; fd will be positioned at the * next timestep. */ static int skip_dcdstep(fio_fd fd, int natoms, int nfixed, int charmm) { int seekoffset = 0; int rec_scale; if (charmm & DCD_HAS_64BIT_REC) { rec_scale=RECSCALE64BIT; } else { rec_scale=RECSCALE32BIT; } /* Skip charmm extra block */ if ((charmm & DCD_IS_CHARMM) && (charmm & DCD_HAS_EXTRA_BLOCK)) { seekoffset += 4*rec_scale + 48 + 4*rec_scale; } /* For each atom set, seek past an int, the free atoms, and another int. */ seekoffset += 3 * (2*rec_scale + natoms - nfixed) * 4; /* Assume that charmm 4th dim is the same size as the other three. */ if ((charmm & DCD_IS_CHARMM) && (charmm & DCD_HAS_4DIMS)) { seekoffset += (2*rec_scale + natoms - nfixed) * 4; } if (fio_fseek(fd, seekoffset, FIO_SEEK_CUR)) return DCD_BADEOF; return DCD_SUCCESS; }
static int read_charmm_extrablock(fio_fd fd, int charmm, int reverseEndian, float *unitcell) { int i, input_integer[2], rec_scale; if (charmm & DCD_HAS_64BIT_REC) { rec_scale = RECSCALE64BIT; } else { rec_scale = RECSCALE32BIT; } if ((charmm & DCD_IS_CHARMM) && (charmm & DCD_HAS_EXTRA_BLOCK)) { /* Leading integer must be 48 */ input_integer[1] = 0; if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD; if (reverseEndian) swap4_aligned(input_integer, rec_scale); if ((input_integer[0]+input_integer[1]) == 48) { double tmp[6]; if (fio_fread(tmp, 48, 1, fd) != 1) return DCD_BADREAD; if (reverseEndian) swap8_aligned(tmp, 6); for (i=0; i<6; i++) unitcell[i] = (float)tmp[i]; } else { /* unrecognized block, just skip it */ if (fio_fseek(fd, (input_integer[0]+input_integer[1]), FIO_SEEK_CUR)) return DCD_BADREAD; } if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD; } return DCD_SUCCESS; }
int jump_to_frame(dcdhandle *dcd, int frame) { int rc; if (frame > dcd->nsets) { return -1; } // Calculate file offset { off_t extrablocksize, ndims, firstframesize, framesize; off_t pos; 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; // Use zero indexing if (frame == 0) { pos = dcd->header_size; dcd->first = 1; } else { pos = dcd->header_size + firstframesize + framesize * (frame-1); dcd->first = 0; } rc = fio_fseek(dcd->fd, pos, FIO_SEEK_SET); } dcd->setsread = frame; return rc; }
/* * Write a timestep to a dcd file * Input: fd - a file struct for which a dcd header has already been written * curframe: Count of frames written to this file, starting with 1. * curstep: Count of timesteps elapsed = istart + curframe * nsavc. * natoms - number of elements in x, y, z arrays * x, y, z: pointers to atom coordinates * Output: 0 on success, negative error code on failure. * Side effects: coordinates are written to the dcd file. */ static int write_dcdstep(fio_fd fd, int curframe, int curstep, int N, const float *X, const float *Y, const float *Z, const double *unitcell, int charmm) { int out_integer; if (charmm) { /* write out optional unit cell */ if (unitcell != NULL) { out_integer = 48; /* 48 bytes (6 floats) */ fio_write_int32(fd, out_integer); WRITE(fd, unitcell, out_integer); fio_write_int32(fd, out_integer); } } /* write out coordinates */ out_integer = N*4; /* N*4 bytes per X/Y/Z array (N floats per array) */ fio_write_int32(fd, out_integer); if (fio_fwrite((void *) X, out_integer, 1, fd) != 1) return DCD_BADWRITE; fio_write_int32(fd, out_integer); fio_write_int32(fd, out_integer); if (fio_fwrite((void *) Y, out_integer, 1, fd) != 1) return DCD_BADWRITE; fio_write_int32(fd, out_integer); fio_write_int32(fd, out_integer); if (fio_fwrite((void *) Z, out_integer, 1, fd) != 1) return DCD_BADWRITE; fio_write_int32(fd, out_integer); /* update the DCD header information */ fio_fseek(fd, NFILE_POS, FIO_SEEK_SET); fio_write_int32(fd, curframe); fio_fseek(fd, NSTEP_POS, FIO_SEEK_SET); fio_write_int32(fd, curstep); fio_fseek(fd, 0, FIO_SEEK_END); return DCD_SUCCESS; }
static int read_js_timestep(void *v, int natoms, molfile_timestep_t *ts) { jshandle *js = (jshandle *)v; int framelen = (natoms * 3 * sizeof(float)) + (6 * sizeof(double));; /* if we have a valid ts pointer, read the timestep, otherwise skip it */ if (ts != NULL) { int readlen; fio_iovec iov[2]; double unitcell[6]; unitcell[0] = unitcell[2] = unitcell[5] = 1.0f; unitcell[1] = unitcell[3] = unitcell[4] = 90.0f; /* setup the I/O vector */ iov[0].iov_base = (fio_caddr_t) ts->coords; /* read coordinates */ iov[0].iov_len = natoms * 3 * sizeof(float); iov[1].iov_base = (fio_caddr_t) &unitcell[0]; /* read PBC unit cell */ iov[1].iov_len = 6 * sizeof(double); /* Do all of the reads with a single syscall, for peak efficiency. */ /* On smart kernels, readv() causes only one context switch, and */ /* can effeciently scatter the reads to the various buffers. */ readlen = fio_readv(js->fd, &iov[0], 2); /* check the number of read bytes versus what we expected */ if (readlen != framelen) return MOLFILE_EOF; /* perform byte swapping if necessary */ if (js->reverseendian) { swap4_aligned(ts->coords, natoms * 3); swap8_aligned(unitcell, 6); } /* copy unit cell values into VMD */ ts->A = unitcell[0]; ts->B = unitcell[1]; ts->C = unitcell[2]; ts->alpha = 90.0 - asin(unitcell[3]) * 90.0 / M_PI_2; ts->beta = 90.0 - asin(unitcell[4]) * 90.0 / M_PI_2; ts->gamma = 90.0 - asin(unitcell[5]) * 90.0 / M_PI_2; } else { /* skip this frame, seek to the next frame */ if (fio_fseek(js->fd, framelen, FIO_SEEK_CUR)) return MOLFILE_EOF; } return MOLFILE_SUCCESS; }
static int read_charmm_4dim(fio_fd fd, int charmm, int reverseEndian) { int input_integer[2],rec_scale; if (charmm & DCD_HAS_64BIT_REC) { rec_scale=RECSCALE64BIT; } else { rec_scale=RECSCALE32BIT; } /* If this is a CHARMm file and contains a 4th dimension block, */ /* we must skip past it to avoid problems */ if ((charmm & DCD_IS_CHARMM) && (charmm & DCD_HAS_4DIMS)) { input_integer[1]=0; if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD; if (reverseEndian) swap4_aligned(input_integer, rec_scale); if (fio_fseek(fd, (input_integer[0]+input_integer[1]), FIO_SEEK_CUR)) return DCD_BADREAD; if (fio_fread(input_integer, sizeof(int), rec_scale, fd) != rec_scale) return DCD_BADREAD; } return DCD_SUCCESS; }
static PyObject * __reset_dcd_read(PyObject *self, PyObject *args) { PyObject* temp; dcdhandle *dcd; int rc; 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; } if ( !PyObject_HasAttrString(self, "_dcd_C_ptr") ) { // Raise exception PyErr_SetString(PyExc_AttributeError, "_dcd_C_ptr is not an attribute"); return NULL; } if ((temp = PyObject_GetAttrString(self, "_dcd_C_ptr")) == NULL) { // This gives me a New Reference // Raise exception PyErr_SetString(PyExc_AttributeError, "_dcd_C_ptr is not an attribute"); return NULL; } dcd = (dcdhandle*)PyCObject_AsVoidPtr(temp); rc = fio_fseek(dcd->fd, dcd->header_size, FIO_SEEK_SET); dcd->setsread = 0; dcd->first = 1; Py_DECREF(temp); Py_INCREF(Py_None); return Py_None; }
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; }
/* * 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 PyObject * __read_timeseries(PyObject *self, PyObject *args) { PyObject *temp = NULL; PyArrayObject *coord = NULL; PyListObject *atoms = NULL; int lowerb = 0, upperb = 0, range=0; float *tempX = NULL, *tempY = NULL, *tempZ = NULL; int rc; int i, j, index; int n_atoms = 0, n_frames = 0; /* Stop = -1 is incorrect and causes an error, look for a fix of this in line 469 */ int start = 0, stop = -1, step = 1, numskip = 0, remaining_frames=0; dcdhandle *dcd = NULL; int *atomlist = NULL; npy_intp dimensions[3]; float unitcell[6]; const char* format = "afc"; if (!self) { /* we were in fact called as a module function, try to retrieve a matching object from args */ if( !PyArg_ParseTuple(args, "OO!|iiis", &self, &PyList_Type, &atoms, &start, &stop, &step, &format) ) return NULL; } else { /* we were obviously called as an object method so args should only have the int value. */ if( !PyArg_ParseTuple(args, "O!|iiis", &PyList_Type, &atoms, &start, &stop, &step, &format) ) return NULL; } if ((temp = PyObject_GetAttrString(self, "_dcd_C_ptr")) == NULL) { // This gives me a New Reference // Raise exception PyErr_SetString(PyExc_AttributeError, "_dcd_C_ptr is not an attribute"); return NULL; } dcd = (dcdhandle*)PyCObject_AsVoidPtr(temp); Py_DECREF(temp); n_frames = ((stop-start) / step); if ((stop-start) % step > 0) { n_frames++; } //n_frames = dcd->nsets / skip; n_atoms = PyList_Size((PyObject*)atoms); if (n_atoms == 0) { PyErr_SetString(PyExc_Exception, "No atoms passed into _read_timeseries function"); return NULL; } atomlist = (int*)malloc(sizeof(int)*n_atoms); memset(atomlist, 0, sizeof(int)*n_atoms); // Get the atom indexes for (i=0;i<n_atoms;i++) { temp = PyList_GetItem((PyObject*)atoms, i); // Borrowed Reference if (temp==NULL) goto error; // Make sure temp is an integer /* TODO: this is not the proper check but [OB] cannot figure out how to check if this is a numpy.int64 or similar; PyInt_Check would fail on those (Issue 18) */ if (!PyArray_IsAnyScalar((PyObject*)temp)) { PyErr_SetString(PyExc_ValueError, "Atom number is not an integer"); goto error; } atomlist[i] = PyInt_AsLong(temp); } lowerb = atomlist[0]; upperb = atomlist[n_atoms-1]; range = upperb-lowerb+1; // Figure out the format string if (strncasecmp(format, "afc", 3) == 0) { dimensions[0] = n_atoms; dimensions[1] = n_frames; dimensions[2] = 3; } else if (strncasecmp(format, "acf", 3) == 0) { dimensions[0] = n_atoms; dimensions[1] = 3; dimensions[2] = n_frames; } else if (strncasecmp(format, "fac", 3) == 0) { dimensions[0] = n_frames; dimensions[1] = n_atoms; dimensions[2] = 3; } else if (strncasecmp(format, "fca", 3) == 0) { dimensions[0] = n_frames; dimensions[1] = 3; dimensions[2] = n_atoms; } else if (strncasecmp(format, "caf", 3) == 0) { dimensions[0] = 3; dimensions[1] = n_atoms; dimensions[2] = n_frames; } else if (strncasecmp(format, "cfa", 3) == 0) { dimensions[0] = 3; dimensions[1] = n_frames; dimensions[2] = n_atoms; } coord = (PyArrayObject*) PyArray_SimpleNew(3, dimensions, NPY_DOUBLE); if (coord == NULL) goto error; // Reset trajectory rc = fio_fseek(dcd->fd, dcd->header_size, FIO_SEEK_SET); dcd->setsread = 0; dcd->first = 1; // Jump to starting frame jump_to_frame(dcd, start); // Now read through trajectory and get the atom pos tempX = (float*)malloc(sizeof(float)*range); tempY = (float*)malloc(sizeof(float)*range); tempZ = (float*)malloc(sizeof(float)*range); if ((tempX == NULL) | (tempY == NULL) || (tempZ == NULL)) { PyErr_SetString(PyExc_MemoryError, "Can't allocate temporary space for coordinate arrays"); goto error; } remaining_frames = stop-start; for (i=0;i<n_frames;i++) { if (step > 1 && i>0) { // Check if we have fixed atoms // XXX not done /* Figure out how many steps to step over, if step = n, np array slicing treats this as skip over n-1, read the nth. */ numskip = step -1; /* If the number to skip is greater than the number of frames left to be jumped over, just take one more step to reflect np slicing if there is a remainder, guaranteed to have at least one more frame. */ if(remaining_frames < numskip){ numskip = 1; } rc = skip_dcdstep(dcd->fd, dcd->natoms, dcd->nfixed, dcd->charmm, numskip); if (rc < 0) { // return an exception PyErr_SetString(PyExc_IOError, "Error skipping frame from DCD file"); goto error; } } // on first iteration, numskip == 0, first set is always read. dcd->setsread += numskip; //now read from subset rc = read_dcdsubset(dcd->fd, dcd->natoms, lowerb, upperb, tempX, tempY, tempZ, unitcell, dcd->nfixed, dcd->first, dcd->freeind, dcd->fixedcoords, dcd->reverse, dcd->charmm); dcd->first = 0; dcd->setsread++; remaining_frames = stop - dcd->setsread; if (rc < 0) { // return an exception PyErr_SetString(PyExc_IOError, "Error reading frame from DCD file"); goto error; } // Copy into Numeric array only those atoms we are interested in for (j=0;j<n_atoms;j++) { index = atomlist[j]-lowerb; /* * coord[a][b][c] = *(float*)(coord->data + a*coord->strides[0] + b*coord->strides[1] + c*coord->strides[2]) */ if (strncasecmp(format, "afc", 3) == 0) { *(double*)(coord->data + j*coord->strides[0] + i*coord->strides[1] + 0*coord->strides[2]) = tempX[index]; *(double*)(coord->data + j*coord->strides[0] + i*coord->strides[1] + 1*coord->strides[2]) = tempY[index]; *(double*)(coord->data + j*coord->strides[0] + i*coord->strides[1] + 2*coord->strides[2]) = tempZ[index]; } else if (strncasecmp(format, "acf", 3) == 0) { *(double*)(coord->data + j*coord->strides[0] + 0*coord->strides[1] + i*coord->strides[2]) = tempX[index]; *(double*)(coord->data + j*coord->strides[0] + 1*coord->strides[1] + i*coord->strides[2]) = tempY[index]; *(double*)(coord->data + j*coord->strides[0] + 2*coord->strides[1] + i*coord->strides[2]) = tempZ[index]; } else if (strncasecmp(format, "fac", 3) == 0) { *(double*)(coord->data + i*coord->strides[0] + j*coord->strides[1] + 0*coord->strides[2]) = tempX[index]; *(double*)(coord->data + i*coord->strides[0] + j*coord->strides[1] + 1*coord->strides[2]) = tempY[index]; *(double*)(coord->data + i*coord->strides[0] + j*coord->strides[1] + 2*coord->strides[2]) = tempZ[index]; } else if (strncasecmp(format, "fca", 3) == 0) { *(double*)(coord->data + i*coord->strides[0] + 0*coord->strides[1] + j*coord->strides[2]) = tempX[index]; *(double*)(coord->data + i*coord->strides[0] + 1*coord->strides[1] + j*coord->strides[2]) = tempY[index]; *(double*)(coord->data + i*coord->strides[0] + 2*coord->strides[1] + j*coord->strides[2]) = tempZ[index]; } else if (strncasecmp(format, "caf", 3) == 0) { *(double*)(coord->data + 0*coord->strides[0] + j*coord->strides[1] + i*coord->strides[2]) = tempX[index]; *(double*)(coord->data + 1*coord->strides[0] + j*coord->strides[1] + i*coord->strides[2]) = tempY[index]; *(double*)(coord->data + 2*coord->strides[0] + j*coord->strides[1] + i*coord->strides[2]) = tempZ[index]; } else if (strncasecmp(format, "cfa", 3) == 0) { *(double*)(coord->data + 0*coord->strides[0] + i*coord->strides[1] + j*coord->strides[2]) = tempX[index]; *(double*)(coord->data + 1*coord->strides[0] + i*coord->strides[1] + j*coord->strides[2]) = tempY[index]; *(double*)(coord->data + 2*coord->strides[0] + i*coord->strides[1] + j*coord->strides[2]) = tempZ[index]; } } // Check if we've been interupted by the user if (PyErr_CheckSignals() == 1) goto error; } // Reset trajectory rc = fio_fseek(dcd->fd, dcd->header_size, FIO_SEEK_SET); dcd->setsread = 0; dcd->first = 1; free(atomlist); free(tempX); free(tempY); free(tempZ); return PyArray_Return(coord); error: // Reset trajectory rc = fio_fseek(dcd->fd, dcd->header_size, FIO_SEEK_SET); dcd->setsread = 0; dcd->first = 1; Py_XDECREF(coord); if (atomlist != NULL) free(atomlist); if (tempX != NULL) free(tempX); if (tempY != NULL) free(tempY); if (tempZ != NULL) free(tempZ); return NULL; }