Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

xyzplugin.c

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

Generated on Mon Jan 20 02:56:37 2020 for VMD Plugins (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002