Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

pqrplugin.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2006 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: pqrplugin.c,v $
00013  *      $Author: johns $       $Locker:  $             $State: Exp $
00014  *      $Revision: 1.12 $       $Date: 2006/02/23 19:36:45 $
00015  *
00016  ***************************************************************************/
00017 
00018 /*
00019  * PQR is be a space-delimited variant of the PDB format, with atom radius
00020  * and charge information replacing the B-factor and occupancy columns, and
00021  * containing only ATOM records.
00022  *
00023  * Most of this code is lifted from pdbplugin and readpdb.h
00024  */
00025 
00026 #include "molfile_plugin.h"
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 
00031 #define PQR_RECORD_LENGTH 80
00032 
00033 /*  record type defines */
00034 enum {PQR_REMARK, PQR_ATOM, PQR_UNKNOWN, PQR_EOF, PQR_ERROR};
00035 
00036 /* 
00037  * read the next record from the specified pqr file, and put the string
00038  * found in the given string pointer (the caller must provide adequate (81
00039  * chars) buffer space); return the type of record found
00040  */
00041 static int read_pqr_record(FILE *f, char *retStr) {
00042 
00043   char inbuf[PQR_RECORD_LENGTH+2];
00044   int recType = PQR_UNKNOWN;
00045  
00046   /* XXX This PQR record reading code breaks with files that use
00047    * Mac or DOS style line breaks with ctrl-M characters.  We need
00048    * to replace the use of fgets() and comparisons against \n with
00049    * code that properly handles the other cases.
00050    */
00051  
00052   /*  read the next line  */
00053   if(inbuf != fgets(inbuf, PQR_RECORD_LENGTH+1, f)) {
00054     retStr[0] = '\0';
00055     if (feof(f)) {
00056       recType = PQR_EOF;
00057     }
00058     else {
00059       recType = PQR_ERROR;
00060     }
00061   } 
00062   else {
00063     /*  remove the newline character, if there is one */
00064     if(inbuf[strlen(inbuf)-1] == '\n')
00065       inbuf[strlen(inbuf)-1] = '\0';
00066 
00067     if (!strncmp(inbuf, "ATOM  ", 6)) {
00068       strcpy(retStr,inbuf);
00069       recType = PQR_ATOM;
00070     } 
00071     else {
00072       retStr[0] = '\0';
00073       recType = PQR_UNKNOWN;
00074     }
00075   }
00076 
00077   /* read the '\r', if there was one */
00078   {
00079     int ch = fgetc(f);
00080     if (ch != '\r') {
00081       ungetc(ch, f);
00082     }
00083   }
00084   
00085   return recType;
00086 }
00087 
00088 /*
00089  * Read the fields in an ATOM line. Return 0 on success, nonzero otherwise.
00090  */
00091 static int get_pqr_fields(char *record, char *name, char *resname, char *chain,
00092     char *segname, char *resid,
00093     float *x, float *y, float *z, float *charge, float *radius) {
00094 
00095   /*
00096    * PQR files are like pdb files, but not quite.  They're fixed format
00097    * for the the identifier data up to resid, but after that it's free-format
00098    * for the floating point data.
00099    */
00100   strncpy(name, record+12, 4);    name[4] = 0;
00101   strncpy(resname, record+17, 4); resname[4] = 0;
00102   strncpy(chain, record+21, 1);   chain[1] = 0;
00103   strncpy(resid, record+22, 4);   resid[4] = 0;
00104   /* XXX what to do about the segid? */
00105   segname[0] = 0;
00106 
00107   if (sscanf(record+30, "%f%f%f%f%f", x, y, z, charge, radius) != 5) {
00108     return 1;
00109   }
00110   /* success */
00111   return 0;
00112 }
00113 
00114 /*
00115  * Read the coordinates in an ATOM line. Return 0 on success, nonzero otherwise.
00116  */
00117 static int get_pqr_coordinates(char *record, float *x, float *y, float *z) {
00118 
00119   if (sscanf(record, "ATOM%*7d  %*4s%*4s%*5s %f%f%f%*f%*f",
00120              x, y, z) == 3) {
00121     return 0;
00122   }
00123 
00124   /* Return an error */
00125   else {
00126     return 1;
00127   }
00128 }
00129 
00130 /*
00131  * Return a default radius for the given atom.
00132  */
00133 static float get_atom_radius(molfile_atom_t *atom) {
00134   char *name, *type;
00135   name = atom->name;
00136   type = atom->type;
00137 
00138   /* XXX - yeah, this needs to be fixed */
00139   return 1.0;
00140 }
00141 
00142 /*
00143  * Append a PQR ATOM record to the given file.
00144  */
00145 static int write_pqr_atom(FILE *fd, int index, const molfile_atom_t *atom, 
00146                    float x, float y, float z) {
00147   int rc;
00148 
00149   rc = fprintf(fd, "ATOM  %5d %-4s %s %5d    %8.3f%8.3f%8.3f %.3f %.3f\n",
00150                index, atom->name, atom->resname, atom->resid, 
00151                x, y, z, atom->charge, atom->radius);
00152 
00153   return (rc > 0);
00154 }
00155 
00156 
00157 /*
00158  * API functions start here
00159  */
00160 
00161 typedef struct {
00162   FILE *fd;
00163   int natoms;
00164   molfile_atom_t *atomlist;
00165 } pqrdata;
00166 
00167 static void *open_pqr_read(const char *filepath, const char *filetype, 
00168     int *natoms) {
00169   FILE *fd;
00170   pqrdata *pqr;
00171   char pqr_record[PQR_RECORD_LENGTH+2];
00172   int record_type;
00173 
00174   fd = fopen(filepath, "r");
00175   if (!fd) 
00176     return NULL;
00177   pqr = (pqrdata *)malloc(sizeof(pqrdata));
00178   pqr->fd = fd;
00179 
00180   *natoms=0;
00181   do {
00182     record_type = read_pqr_record(pqr->fd, pqr_record);
00183     if (record_type == PQR_ATOM)
00184       *natoms += 1;
00185     else if (record_type == PQR_ERROR) {
00186       fprintf(stderr, "Error reading PQR file after opening.\n");
00187       free(pqr);
00188       return NULL;
00189     }
00190     /* else, do nothing */
00191   } while (record_type != PQR_EOF);
00192 
00193   /* If no atoms were found, this is probably not a PQR file! */
00194   if (!*natoms) {
00195     fprintf(stderr, "PQR file '%s' contains no atoms.\n", filepath);
00196     free(pqr);
00197     return NULL;
00198   }
00199 
00200   rewind(pqr->fd);
00201   pqr->natoms = *natoms;
00202   return pqr; 
00203 }
00204 
00205 /* 
00206  * Read atom structure, but not coordinate information.
00207  */
00208 static int read_pqr_structure(void *mydata, int *optflags, 
00209     molfile_atom_t *atoms) { 
00210   pqrdata *pqr = (pqrdata *)mydata;
00211   molfile_atom_t *atom;
00212   char pqr_record[PQR_RECORD_LENGTH + 1];
00213   int i, record_type;
00214   char ridstr[8];
00215   float newpos;
00216   long fpos = ftell(pqr->fd);
00217  
00218   *optflags = MOLFILE_CHARGE | MOLFILE_RADIUS;
00219 
00220   i = 0;
00221   do {
00222     record_type = read_pqr_record(pqr->fd, pqr_record);
00223     if ( (record_type == PQR_EOF) && (i < pqr->natoms) ) {
00224       fprintf(stderr, "Unexpected end-of-file.\n");
00225       return MOLFILE_ERROR;
00226     } 
00227     else if (record_type == PQR_ERROR) {
00228       fprintf(stderr, "Error reading atom coordinates.\n");
00229       return MOLFILE_ERROR;
00230     }
00231     else if (record_type == PQR_ATOM) {
00232       if (i >= pqr->natoms) {
00233         fprintf(stderr, "Too many atoms.\n");
00234         return MOLFILE_ERROR;
00235       }
00236       atom = atoms+i;
00237       get_pqr_fields(pqr_record, atom->name, atom->resname, atom->chain, 
00238           atom->segid, ridstr,
00239           &newpos, &newpos, &newpos, &atom->charge, &atom->radius);
00240       atom->resid = atoi(ridstr);
00241       strcpy(atom->type, atom->name);
00242       i++;
00243     }
00244     else {
00245       /* XXX do stuff */
00246     }
00247   } while(record_type != PQR_EOF);
00248 
00249   fseek(pqr->fd, fpos, SEEK_SET);
00250 
00251   return MOLFILE_SUCCESS;
00252 }
00253 
00254 /* 
00255  * Read atom coordinates. PQR files contain only a single "timestep".
00256  */
00257 static int read_pqr_timestep(void *v, int natoms, molfile_timestep_t *ts) {
00258   pqrdata *pqr = (pqrdata *)v;
00259   char pqr_record[PQR_RECORD_LENGTH+2];
00260   int record_type, i;
00261   float *x, *y, *z;
00262 
00263   if (pqr->natoms == 0) 
00264     return MOLFILE_ERROR; /* EOF */
00265   if (ts) {
00266     x = ts->coords;
00267     y = x+1;
00268     z = x+2;
00269   } else {
00270     x = y = z = 0;
00271   }
00272 
00273   i = 0;
00274   do {
00275     record_type = read_pqr_record(pqr->fd, pqr_record);
00276     if ( (record_type == PQR_EOF) && (i < pqr->natoms) ) {
00277       fprintf(stderr, "Unexpected end-of-file.\n");
00278       return MOLFILE_ERROR;
00279     } 
00280     else if (record_type == PQR_ERROR) {
00281       fprintf(stderr, "Error reading atom coordinates.\n");
00282       return MOLFILE_ERROR;
00283     }
00284     else if (record_type == PQR_ATOM) {
00285       /* just get the coordinates, and store them */
00286       if (ts) {
00287         get_pqr_coordinates(pqr_record, x, y, z);
00288         x += 3;
00289         y += 3;
00290         z += 3;
00291         i++;
00292       } 
00293     }
00294     else {
00295       /* XXX do stuff */
00296     }
00297   } while(i < pqr->natoms);
00298 
00299   return MOLFILE_SUCCESS;
00300 }
00301 
00302 static void close_pqr_read(void *v) { 
00303   pqrdata *pqr = (pqrdata *)v;
00304   if (pqr->fd) {
00305     fclose(pqr->fd);
00306     pqr->fd = 0;
00307   }
00308   free(pqr);
00309 }
00310 
00311 static void *open_pqr_write(const char *path, const char *filetype, 
00312     int natoms) {
00313   FILE *fd;
00314   pqrdata *pqr;
00315   fd = fopen(path, "w");
00316   if (!fd) {
00317     fprintf(stderr, "Unable to open file %s for writing\n", path);
00318     return NULL;
00319   }
00320 
00321   pqr = (pqrdata *)malloc(sizeof(pqrdata));
00322   pqr->fd = fd;
00323   pqr->natoms = natoms; 
00324   pqr->atomlist = NULL;
00325   return pqr;
00326 }
00327  
00328 static int write_pqr_structure(void *v, int optflags, 
00329     const molfile_atom_t *atoms) {
00330   int i;
00331   pqrdata *pqr = (pqrdata *)v;
00332   int natoms = pqr->natoms;
00333   pqr->atomlist = (molfile_atom_t *)malloc(natoms*sizeof(molfile_atom_t));
00334 
00335   memcpy(pqr->atomlist, atoms, natoms*sizeof(molfile_atom_t));
00336 
00337   /* If charge and radius aren't given, we assign defaultvalues. */
00338   if (!(optflags & MOLFILE_CHARGE)) {
00339     for (i=0; i<natoms; i++) pqr->atomlist[i].charge = 0.0f;
00340   }
00341   if (!(optflags & MOLFILE_RADIUS)) {
00342     for (i=0; i<natoms; i++) pqr->atomlist[i].radius = 
00343       get_atom_radius(&(pqr->atomlist[i]));
00344   }
00345 
00346   return MOLFILE_SUCCESS;
00347 }
00348 
00349 static int write_pqr_timestep(void *v, const molfile_timestep_t *ts) {
00350   pqrdata *pqr = (pqrdata *)v; 
00351   const molfile_atom_t *atom;
00352   const float *pos;
00353   int i;
00354 
00355   if (pqr->natoms == 0)
00356     return MOLFILE_SUCCESS;
00357 
00358   atom = pqr->atomlist;
00359   pos = ts->coords;
00360   for (i=0; i<pqr->natoms; i++) {
00361     if (!write_pqr_atom(pqr->fd, i+1, atom, pos[0], pos[1], pos[2])) {
00362       fprintf(stderr, 
00363         "PQR: Error encoutered writing atom %d; file may be incomplete.\n", 
00364         i+1);
00365       return MOLFILE_ERROR;
00366     }
00367     atom++;
00368     pos += 3;
00369   }
00370 
00371   return MOLFILE_SUCCESS;
00372 }
00373  
00374 static void close_pqr_write(void *v) {
00375   pqrdata *pqr = (pqrdata *)v; 
00376   fclose(pqr->fd);
00377   free(pqr->atomlist);
00378   free(pqr);
00379 }
00380 
00381 /*
00382  * Initialization stuff down here
00383  */
00384 
00385 static molfile_plugin_t plugin = {
00386   vmdplugin_ABIVERSION,         /* ABI version */
00387   MOLFILE_PLUGIN_TYPE,          /* type */
00388   "pqr",                        /* short name */
00389   "PQR",                        /* pretty name */
00390   "Eamon Caddigan",             /* author */
00391   0,                            /* major version */
00392   1,                            /* minor version */
00393   VMDPLUGIN_THREADSAFE,         /* is_reentrant */
00394   "pqr",                        /* filename extension */
00395   open_pqr_read,
00396   read_pqr_structure,
00397   0,
00398   read_pqr_timestep,
00399   close_pqr_read,
00400   open_pqr_write,
00401   write_pqr_structure,
00402   write_pqr_timestep,
00403   close_pqr_write
00404 };
00405  
00406 VMDPLUGIN_API int VMDPLUGIN_init() {
00407   return VMDPLUGIN_SUCCESS;
00408 }
00409 
00410 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00411   (*cb)(v, (vmdplugin_t *)&plugin);
00412   return VMDPLUGIN_SUCCESS;
00413 }
00414 
00415 VMDPLUGIN_API int VMDPLUGIN_fini() {
00416   return VMDPLUGIN_SUCCESS;
00417 }
00418 

Generated on Wed Mar 22 13:15:31 2006 for VMD Plugins (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002