Пример #1
0
static PyObject *
__read_next_frame(PyObject *self, PyObject *args)
{
  dcdhandle *dcd;
  PyObject *temp;
  PyArrayObject *x, *y, *z, *uc;
  int skip=1;
  int rc,numskip;
  float* unitcell;
  float alpha, beta, gamma;

  if (!self) {
    /* we were in fact called as a module function, try to retrieve
       a matching object from args */
    if( !PyArg_ParseTuple(args, "OO!O!O!O!|i", &self, &PyArray_Type, &x, &PyArray_Type, &y, &PyArray_Type, &z, &PyArray_Type, &uc, &skip) )
      return NULL;
  } else {
    /* we were obviously called as an object method so args should
       only have the int value. */
    if( !PyArg_ParseTuple(args, "O!O!O!O!|i", &PyArray_Type, &x, &PyArray_Type, &y, &PyArray_Type, &z, &PyArray_Type, &uc, &skip) )
      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);

  unitcell = (float*) uc->data;
  unitcell[0] = unitcell[2] = unitcell[5] = 0.0f;
  unitcell[1] = unitcell[3] = unitcell[4] = 90.0f;

  /* Check for EOF here; that way all EOF's encountered later must be errors */
  if (dcd->setsread == dcd->nsets) {
    // Is this an exception?
    PyErr_SetString(PyExc_IOError, "End of file reached for dcd file");
    return NULL;
    //return MOLFILE_EOF;
  }
  if (skip > 1) {
    if (dcd->first && dcd->nfixed) {
      /* We can't just skip it because we need the fixed atom coordinates */
      rc = read_dcdstep(dcd->fd, dcd->natoms, (float*)x->data, (float*)y->data, (float*)z->data,
			unitcell, dcd->nfixed, dcd->first, dcd->freeind, dcd->fixedcoords,
			dcd->reverse, dcd->charmm);
      dcd->first = 0;
      if (rc < 0) {
        // return an exception
        PyErr_SetString(PyExc_IOError, "Error reading first frame from DCD file");
        //fprintf(stderr, "read_dcdstep returned %d\n", rc);
        return NULL;
        //return MOLFILE_ERROR;
      }
      dcd->setsread++;
      temp = Py_BuildValue("i", dcd->setsread);
      return temp;
      //return rc; /* XXX this needs to be updated */
    }
    dcd->first = 0;
    // Figure out how many steps to skip
    numskip = skip - (dcd->setsread % skip) - 1;
    /* XXX this needs to be changed */
    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");
      //fprintf(stderr, "read_dcdstep returned %d\n", rc);
      return NULL;
      //return MOLFILE_ERROR;
    }
    dcd->setsread+=numskip;
  }
  rc = read_dcdstep(dcd->fd, dcd->natoms, (float*)x->data, (float*)y->data, (float*)z->data, unitcell,
		    dcd->nfixed, dcd->first, dcd->freeind, dcd->fixedcoords,
		    dcd->reverse, dcd->charmm);
  dcd->first = 0;
  dcd->setsread++;
  if (rc < 0) {
    // return an exception
    PyErr_SetString(PyExc_IOError, "Error reading frame from DCD file");
    //fprintf(stderr, "read_dcdstep returned %d\n", rc);
    return NULL;
    //return MOLFILE_ERROR;
  }

  if (unitcell[1] >= -1.0 && unitcell[1] <= 1.0 &&
      unitcell[3] >= -1.0 && unitcell[3] <= 1.0 &&
      unitcell[4] >= -1.0 && unitcell[4] <= 1.0) {
    /* This file was generated by Charmm, or by NAMD > 2.5, with the angle */
    /* cosines of the periodic cell angles written to the DCD file.        */
    /* This formulation improves rounding behavior for orthogonal cells    */
    /* so that the angles end up at precisely 90 degrees, unlike acos().   */
    /* (changed in MDAnalysis 0.9.0 to have NAMD ordering of the angles;   */
    /* see Issue 187) */
    alpha = 90.0 - asin(unitcell[4]) * 90.0 / M_PI_2;
    beta  = 90.0 - asin(unitcell[3]) * 90.0 / M_PI_2;
    gamma = 90.0 - asin(unitcell[1]) * 90.0 / M_PI_2;
  } else {
    /* This file was likely generated by NAMD 2.5 and the periodic cell    */
    /* angles are specified in degrees rather than angle cosines.          */
    alpha = unitcell[4];
    beta  = unitcell[3];
    gamma = unitcell[1];
  }
  unitcell[4] = alpha;
  unitcell[3] = beta;
  unitcell[1] = gamma;

  // Return the frame read
  temp = Py_BuildValue("i", dcd->setsread);
  return temp;
}
Пример #2
0
static int read_next_timestep(void *v, int natoms, molfile_timestep_t *ts) {
  dcdhandle *dcd;
  int i, j, rc;
  float unitcell[6];
  unitcell[0] = unitcell[2] = unitcell[5] = 1.0f;
  unitcell[1] = unitcell[3] = unitcell[4] = 90.0f;
  dcd = (dcdhandle *)v;

  /* Check for EOF here; that way all EOF's encountered later must be errors */
  if (dcd->setsread == dcd->nsets) return MOLFILE_EOF;
  dcd->setsread++;
  if (!ts) {
    if (dcd->first && dcd->nfixed) {
      /* We can't just skip it because we need the fixed atom coordinates */
      rc = read_dcdstep(dcd->fd, dcd->natoms, dcd->x, dcd->y, dcd->z, 
          unitcell, dcd->nfixed, dcd->first, dcd->freeind, dcd->fixedcoords, 
             dcd->reverse, dcd->charmm);
      dcd->first = 0;
      return rc; /* XXX this needs to be updated */
    }
    dcd->first = 0;
    /* XXX this needs to be changed */
    return skip_dcdstep(dcd->fd, dcd->natoms, dcd->nfixed, dcd->charmm);
  }
  rc = read_dcdstep(dcd->fd, dcd->natoms, dcd->x, dcd->y, dcd->z, unitcell,
             dcd->nfixed, dcd->first, dcd->freeind, dcd->fixedcoords, 
             dcd->reverse, dcd->charmm);
  dcd->first = 0;
  if (rc < 0) {  
    print_dcderror("read_dcdstep", rc);
    return MOLFILE_ERROR;
  }

  /* copy timestep data from plugin-local buffers to VMD's buffer */
  /* XXX 
   *   This code is still the root of all evil.  Just doing this extra copy
   *   cuts the I/O rate of the DCD reader from 728 MB/sec down to
   *   394 MB/sec when reading from a ram filesystem.  
   *   For a physical disk filesystem, the I/O rate goes from 
   *   187 MB/sec down to 122 MB/sec.  Clearly this extra copy has to go.
   */
  {
    int natoms = dcd->natoms;
    float *nts = ts->coords;
    const float *bufx = dcd->x;
    const float *bufy = dcd->y;
    const float *bufz = dcd->z;

    for (i=0, j=0; i<natoms; i++, j+=3) {
      nts[j    ] = bufx[i];
      nts[j + 1] = bufy[i];
      nts[j + 2] = bufz[i];
    }
  }

  ts->A = unitcell[0];
  ts->B = unitcell[2];
  ts->C = unitcell[5];

  if (unitcell[1] >= -1.0 && unitcell[1] <= 1.0 &&
      unitcell[3] >= -1.0 && unitcell[3] <= 1.0 &&
      unitcell[4] >= -1.0 && unitcell[4] <= 1.0) {
    /* This file was generated by CHARMM, or by NAMD > 2.5, with the angle */
    /* cosines of the periodic cell angles written to the DCD file.        */ 
    /* This formulation improves rounding behavior for orthogonal cells    */
    /* so that the angles end up at precisely 90 degrees, unlike acos().   */
    ts->alpha = 90.0 - asin(unitcell[4]) * 90.0 / M_PI_2; /* cosBC */
    ts->beta  = 90.0 - asin(unitcell[3]) * 90.0 / M_PI_2; /* cosAC */
    ts->gamma = 90.0 - asin(unitcell[1]) * 90.0 / M_PI_2; /* cosAB */
  } else {
    /* This file was likely generated by NAMD 2.5 and the periodic cell    */
    /* angles are specified in degrees rather than angle cosines.          */
    ts->alpha = unitcell[4]; /* angle between B and C */
    ts->beta  = unitcell[3]; /* angle between A and C */
    ts->gamma = unitcell[1]; /* angle between A and B */
  }
 
  return MOLFILE_SUCCESS;
}
Пример #3
0
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;
}