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

xyzplugin.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: xyzplugin.c,v $
00013  *      $Author: johns $       $Locker:  $             $State: Exp $
00014  *      $Revision: 1.31 $       $Date: 2006/02/23 19:36:46 $
00015  *
00016  ***************************************************************************/
00017 
00018 /*
00019  *  XYZ molecule file format:
00020  *    XYZ files are a simple molecule file format suitable for output
00021  *    by homegrown software since they are very minimalistic.  They don't
00022  *    even include bonding information.
00023  *
00024  *  [ # optional comment line ] comment line (can be blank)
00025  *                              ^^^ note, this is not supported by the current
00026  *                                  version of this plugin.
00027  *  [ N                       ] # of atoms, required by this xyz reader plugin
00028  *  [ molecule name           ] name of molecule (can be blank)
00029  *  atom1 x y z [optional data] atom name followed by xyz coords 
00030  *  atom2 x y z [ ...         ] and (optionally) other data.
00031  *  ...                         instead of atom name the atom number in 
00032  *  atomN x y z [ ...         ] the PTE can be given.
00033  *                      
00034  *  Note that this plugin currently ignores everything following the z 
00035  *  coordinate (the optional data fields).
00036  */
00037 
00038 #include "largefiles.h"   /* platform dependent 64-bit file I/O defines */
00039 
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #include <ctype.h>
00044 #include "molfile_plugin.h"
00045 
00046 #include "periodic_table.h"
00047 
00048 typedef struct {
00049   FILE *file;
00050   int numatoms;
00051   char *file_name;
00052   molfile_atom_t *atomlist;
00053 } xyzdata;
00054  
00055 static void *open_xyz_read(const char *filename, const char *filetype, 
00056                            int *natoms) {
00057   FILE *fd;
00058   xyzdata *data;
00059   int i;
00060 
00061   fd = fopen(filename, "rb");
00062   if (!fd) return NULL;
00063   
00064   data = (xyzdata *)malloc(sizeof(xyzdata));
00065   data->file = fd;
00066   data->file_name = strdup(filename);
00067 
00068   /* First line is the number of atoms   */
00069   i = fscanf(data->file, "%d", natoms);
00070   if (i < 1) {
00071     fprintf(stderr, "\n\nread) ERROR: xyz file '%s' should have the number of atoms in the first line.\n", filename);
00072     return NULL;
00073   }
00074   data->numatoms=*natoms;
00075 
00076   while (getc(fd) != '\n');
00077   /* second line is a title or empty, so skip past it */
00078   while (getc(fd) != '\n');
00079   
00080   return data;
00081 }
00082 
00083 static int read_xyz_structure(void *mydata, int *optflags, 
00084                               molfile_atom_t *atoms) {
00085   int i, j;
00086   char *k;
00087   float coord;
00088   molfile_atom_t *atom;
00089   xyzdata *data = (xyzdata *)mydata;
00090 
00091   /* we set atom mass and VDW radius from the PTE. */
00092   *optflags = MOLFILE_ATOMICNUMBER | MOLFILE_MASS | MOLFILE_RADIUS; 
00093 
00094   for(i=0; i<data->numatoms; i++) {
00095     char buffer[1024], fbuffer[1024];
00096     k = fgets(fbuffer, 1024, data->file);
00097     atom = atoms + i;
00098     j=sscanf(fbuffer, "%s %f %f %f", buffer, &coord, &coord, &coord);
00099     if (k == NULL) {
00100       fprintf(stderr, "xyz structure) missing atom(s) in file '%s'\n", data->file_name);
00101       fprintf(stderr, "xyz structure) expecting '%d' atoms, found only '%d'\n", data->numatoms, i);
00102       return MOLFILE_ERROR;
00103     } else if (j < 4) {
00104       fprintf(stderr, "xyz structure) missing type or coordinate(s) in file '%s' for atom '%d'\n",
00105           data->file_name, i+1);
00106       return MOLFILE_ERROR;
00107     }
00108 
00109     /* handle the case if the first item is an ordinal number 
00110      * from the PTE */
00111     if (isdigit(buffer[0])) {
00112       int idx;
00113       idx = atoi(buffer);
00114       strncpy(atom->name, get_pte_label(idx), sizeof(atom->name));
00115       atom->atomicnumber = idx;
00116       atom->mass = get_pte_mass(idx);
00117       atom->radius = get_pte_vdw_radius(idx);
00118     } else {
00119       int idx;
00120       strncpy(atom->name, buffer, sizeof(atom->name));
00121       idx = get_pte_idx(buffer);
00122       atom->atomicnumber = idx;
00123       atom->mass = get_pte_mass(idx);
00124       atom->radius = get_pte_vdw_radius(idx);
00125     }
00126     strncpy(atom->type, atom->name, sizeof(atom->type));
00127     atom->resname[0] = '\0';
00128     atom->resid = 1;
00129     atom->chain[0] = '\0';
00130     atom->segid[0] = '\0';
00131     /* skip to the end of line */
00132   }
00133 
00134   rewind(data->file);
00135   return MOLFILE_SUCCESS;
00136 }
00137 
00138 static int read_xyz_timestep(void *mydata, int natoms, molfile_timestep_t *ts) {
00139   int i, j;
00140   char atom_name[1024], fbuffer[1024], *k;
00141   float x, y, z;
00142   
00143   xyzdata *data = (xyzdata *)mydata;
00144   
00145   /* skip over the first two lines */
00146   if (NULL == fgets(fbuffer, 1024, data->file))  return MOLFILE_ERROR;
00147   if (NULL == fgets(fbuffer, 1024, data->file))  return MOLFILE_ERROR;
00148 
00149   /* read the coordinates */
00150   for (i=0; i<natoms; i++) {
00151     k = fgets(fbuffer, 1024, data->file);
00152 
00153     /* Read in atom type, X, Y, Z, skipping any remaining data fields */
00154     j = sscanf(fbuffer, "%s %f %f %f", atom_name, &x, &y, &z);
00155     if (k == NULL) {
00156       return MOLFILE_ERROR;
00157     } else if (j < 4) {
00158       fprintf(stderr, "xyz timestep) missing type or coordinate(s) in file '%s' for atom '%d'\n",data->file_name,i+1);
00159       return MOLFILE_ERROR;
00160     } else if (j >= 4) {
00161       if (ts != NULL) { 
00162         /* only save coords if we're given a timestep pointer, */
00163         /* otherwise assume that VMD wants us to skip past it. */
00164         ts->coords[3*i  ] = x;
00165         ts->coords[3*i+1] = y;
00166         ts->coords[3*i+2] = z;
00167       }
00168     } else {
00169       break;
00170     }
00171   }
00172   
00173   return MOLFILE_SUCCESS;
00174 }
00175     
00176 static void close_xyz_read(void *mydata) {
00177   xyzdata *data = (xyzdata *)mydata;
00178   fclose(data->file);
00179   free(data->file_name);
00180   free(data);
00181 }
00182 
00183 
00184 static void *open_xyz_write(const char *filename, const char *filetype, 
00185                            int natoms) {
00186   FILE *fd;
00187   xyzdata *data;
00188 
00189   fd = fopen(filename, "w");
00190   if (!fd) { 
00191     fprintf(stderr, "Error) Unable to open xyz file %s for writing\n",
00192             filename);
00193     return NULL;
00194   }
00195   
00196   data = (xyzdata *)malloc(sizeof(xyzdata));
00197   data->numatoms = natoms;
00198   data->file = fd;
00199   data->file_name = strdup(filename);
00200   return data;
00201 }
00202 
00203 static int write_xyz_structure(void *mydata, int optflags, 
00204                                const molfile_atom_t *atoms) {
00205   xyzdata *data = (xyzdata *)mydata;
00206   data->atomlist = (molfile_atom_t *)malloc(data->numatoms*sizeof(molfile_atom_t));
00207   memcpy(data->atomlist, atoms, data->numatoms*sizeof(molfile_atom_t));
00208   return MOLFILE_SUCCESS;
00209 }
00210 
00211 static int write_xyz_timestep(void *mydata, const molfile_timestep_t *ts) {
00212   xyzdata *data = (xyzdata *)mydata; 
00213   const molfile_atom_t *atom;
00214   const float *pos;
00215   int i;
00216 
00217   fprintf(data->file, "%d\n", data->numatoms);
00218   fprintf(data->file, " generated by VMD\n");
00219   
00220   atom = data->atomlist;
00221   pos = ts->coords;
00222   for (i = 0; i < data->numatoms; ++i) {
00223     fprintf(data->file, " %-2s %15.6f %15.6f %15.6f\n", 
00224             atom->type, pos[0], pos[1], pos[2]);
00225     ++atom; 
00226     pos += 3;
00227   }
00228   return MOLFILE_SUCCESS;
00229 }
00230 
00231 
00232 static void close_xyz_write(void *mydata) {
00233   xyzdata *data = (xyzdata *)mydata;
00234   fclose(data->file);
00235   free(data->atomlist);
00236   free(data->file_name);
00237   free(data);
00238 }
00239 
00240 /* registration stuff */
00241 static molfile_plugin_t xyzplugin = {
00242   vmdplugin_ABIVERSION,
00243   MOLFILE_PLUGIN_TYPE,                         /* type */
00244   "xyz",                                       /* name */
00245   "XYZ",                                       /* name */
00246   "Mauricio Carrillo Tripp, John E. Stone, Axel Kohlmeyer",    /* author */
00247   0,                                           /* major version */
00248   9,                                           /* minor version */
00249   VMDPLUGIN_THREADSAFE,                        /* is reentrant */
00250   "xyz",
00251   open_xyz_read,
00252   read_xyz_structure,
00253   0,
00254   read_xyz_timestep,
00255   close_xyz_read,
00256   open_xyz_write,
00257   write_xyz_structure,
00258   write_xyz_timestep,
00259   close_xyz_write,
00260   0,                            /* read_volumetric_metadata */
00261   0,                            /* read_volumetric_data */
00262   0                             /* read_rawgraphics */
00263 };
00264 
00265 VMDPLUGIN_API int VMDPLUGIN_init() {
00266   return VMDPLUGIN_SUCCESS;
00267 }
00268 
00269 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00270   (*cb)(v, (vmdplugin_t *)&xyzplugin);
00271   return VMDPLUGIN_SUCCESS;
00272 }
00273 
00274 VMDPLUGIN_API int VMDPLUGIN_fini() {
00275   return VMDPLUGIN_SUCCESS;
00276 }
00277 
00278 
00279 #ifdef TEST_PLUGIN
00280 
00281 int main(int argc, char *argv[]) {
00282   molfile_timestep_t timestep;
00283   void *v;
00284   int natoms;
00285   int i, nsets, set;
00286 
00287   while (--argc) {
00288     ++argv;
00289     v = open_xyz_read(*argv, "xyz", &natoms);
00290     if (!v) {
00291       fprintf(stderr, "open_xyz_read failed for file %s\n", *argv);
00292       return 1;
00293     }
00294     fprintf(stderr, "open_xyz_read succeeded for file %s\n", *argv);
00295     fprintf(stderr, "number of atoms: %d\n", natoms);
00296 
00297     i = 0;
00298     timestep.coords = (float *)malloc(3*sizeof(float)*natoms);
00299     while (!read_xyz_timestep(v, natoms, &timestep)) {
00300       i++;
00301     }
00302     fprintf(stderr, "ended read_next_timestep on frame %d\n", i);
00303 
00304     close_xyz_read(v);
00305   }
00306   return 0;
00307 }
00308 
00309 #endif
00310 

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