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

babelplugin.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: babelplugin.c,v $
00013  *      $Author: johns $       $Locker:  $             $State: Exp $
00014  *      $Revision: 1.49 $       $Date: 2016/11/28 05:01:53 $
00015  *
00016  ***************************************************************************/
00017 
00018 /*
00019  * Convert files using Babel 1.6
00020  *   http://www.eyesopen.com/products/applications/babel.html
00021  *
00022  * Convert files using Open Babel 1.100.2
00023  *   http://openbabel.sourceforge.net/babel.shtml
00024  */
00025 
00026 
00027 #include <stdlib.h>
00028 #include <ctype.h>
00029 #include <string.h>
00030 
00031 #if !defined(_MSC_VER) 
00032 #include <unistd.h>  /* for getuid */
00033 #endif
00034 
00035 #include "molfile_plugin.h"
00036 #include "readpdb.h"
00037 #include "vmddir.h"
00038 #include "periodic_table.h"
00039 
00040 typedef struct {
00041   FILE *fd;
00042   int natoms;
00043   char *original_file;
00044   char *current_file;
00045   int babel_num;
00046   int babel_i;
00047 } pdbdata;
00048 
00049 /* 
00050  * I guess this is to try to keep tmp files from clobbering each other
00051  */
00052 static int vmd_getuid(void) {
00053 #if defined(_MSC_VER)
00054   return 0;
00055 #else
00056   return getuid();
00057 #endif
00058 }
00059 
00060 static int vmd_delete_file(const char * path) {
00061 #if defined(_MSC_VER)
00062   if (DeleteFile(path) == 0)
00063     return -1;
00064   else
00065     return 0;
00066 #else
00067   return unlink(path);
00068 #endif
00069 }
00070 
00071 #define BABEL_TMPDIR "/tmp/"
00072 
00073 /*
00074  * Dude, don't even think for a minute that I came up with this code.  It's
00075  * copied from BabelConvert.C, ok?
00076  * This gets called three times, with has_multi = 1, -2, and -1.  Don't ask
00077  * me why.
00078  */
00079 static char *file(const char *filename, int idx, int has_multi) {
00080    /* temp space to save the filename or glob */
00081    int i=0;
00082    char *ptr;
00083    char *tempspace = (char *)malloc(513);
00084    const char *s;
00085    for (s = filename; *s != 0; s++) { 
00086       if ((*s == '/') || (*s == '\\'))
00087         i = s-filename+1;
00088    }
00089    /*
00090    // so filename+i points to the actual name
00091    // if there are multiple files in the conversion, then the output
00092    // looks like "test0041.extensions".  If there was a single file,
00093    // the output looks like "test.extensions"
00094    */
00095    if (has_multi == -1) {
00096       sprintf(tempspace, "%svmdbabel*.u%d.%s", BABEL_TMPDIR,
00097               vmd_getuid(), filename + i);
00098    } else if (has_multi == -2) {
00099       char *reallytemp = (char *)malloc(strlen(filename+i)+1);
00100       strcpy(reallytemp, filename+i);
00101       *(reallytemp + strlen(reallytemp) - 1) = 0;
00102       sprintf(tempspace, "vmdbabel%%[0-9.]u%d.%s%%c",
00103               vmd_getuid(), reallytemp);
00104       free(reallytemp);
00105    } else if (has_multi == 0) {
00106       sprintf(tempspace, "%svmdbabel.u%d.%s", BABEL_TMPDIR,
00107               vmd_getuid(), filename + i);
00108    } else {
00109       sprintf(tempspace, "%svmdbabel%04d.u%d.%s", BABEL_TMPDIR, idx+1,
00110               vmd_getuid(), filename + i);
00111    }
00112    for (ptr = tempspace; *ptr; ptr++) {  /* babel makes them lowercase! */
00113       *ptr = tolower(*ptr);              /* grrrrrrr                    */
00114    }
00115    return tempspace;
00116 }
00117 
00118 static void delete_all(const char *filename) {
00119   const char *s;
00120   char *t;
00121 
00122   s = file(filename, 0, -1); /* puts a '*' in number field */
00123   t = (char *)malloc(strlen(s) + 35);
00124 #if defined(_MSC_VER)
00125    sprintf(t, "del %s", s);
00126 #else
00127    sprintf(t, "/bin/rm -f \"%s\"", s);
00128 #endif
00129   system(t);
00130   free(t);
00131 }
00132  
00133 static void *open_pdb_read(const char *filepath, int *natoms) {
00134   FILE *fd;
00135   pdbdata *pdb;
00136   char pdbstr[PDB_BUFFER_LENGTH];
00137   int indx;
00138   fd = fopen(filepath, "r");
00139   if (!fd) return NULL;
00140   pdb = (pdbdata *)malloc(sizeof(pdbdata));
00141   pdb->fd = fd;
00142   *natoms = 0;
00143   do {
00144     if((indx = read_pdb_record(pdb->fd, pdbstr)) == PDB_ATOM)
00145       *natoms += 1;
00146   } while (indx != PDB_END && indx != PDB_EOF);
00147   rewind(pdb->fd);
00148   pdb->natoms = *natoms;
00149   return pdb;
00150 }
00151 
00152 /*
00153  * Babel 1.6 internal file type names
00154  */
00155 static const char *babel16filetypes[] = {
00156 "alc",
00157 "prep",
00158 "bs",
00159 "bgf",
00160 "car",
00161 "boog",
00162 "caccrt",
00163 "cadpac",
00164 "charmm",
00165 "c3d1",
00166 "c3d2",
00167 "cssr",
00168 "fdat",
00169 "gstat",
00170 "dock",
00171 "dpdb",
00172 "feat",
00173 "fract",
00174 "gamout",
00175 "gzmat",
00176 "gauout",
00177 "g94",
00178 "gr96A",
00179 "gr96N",
00180 "hin",
00181 "sdf",
00182 "m3d",
00183 "macmol",
00184 "macmod",
00185 "micro",
00186 "mm2in",
00187 "mm2out",
00188 "mm3",
00189 "mmads",
00190 "mdl",
00191 "molen",
00192 "mopcrt",
00193 "mopint",
00194 "mopout",
00195 "pcmod",
00196 "psin",
00197 "psout",
00198 "msf",
00199 "schakal",
00200 "shelx",
00201 "smiles",
00202 "spar",
00203 "semi",
00204 "spmm",
00205 "mol",
00206 "mol2",
00207 "wiz",
00208 "unixyz",
00209 "xyz",  
00210 "xed",
00211 0
00212 };
00213 
00214 /*
00215  * Plugin names registered in VMD for each Babel 1.6 file type
00216  */
00217 static const char *babel16filetypenames[] = {
00218   "Alchemy",          "AMBERPREP",       "BallStick",      
00219   "MSIBGF",           "BiosymCAR",       "Boogie",
00220   "Cacao",            "CADPAC",          "CHARMm",
00221   "Chem3d-1",         "Chem3d-2",        "CSSR",
00222   "FDAT",             "GSTAT",           "Dock",
00223   "DockPDB",          "Feature",         "Fractional",    
00224   "GAMESSoutput",     "GaussianZmatrix", "Gaussian92output", 
00225   "Gaussian94output", "Gromos96A",       "Gromos96N",
00226   "HyperchemHIN",     "IsisSDF",         "M3D",
00227   "MacMolecule",      "Macromodel",      "MicroWorld",
00228   "MM2Input",         "MM2Output",       "MM3",
00229   "MMADS",            "MDLMOL",          "MOLIN",
00230   "MopacCartesian",   "MopacInternal",   "MopacOutput",
00231   "PCModel",          "PSGVBin",         "PSGVBout",
00232   "QuantaMSF",        "Schakal",         "ShelX",
00233   "SMILES",
00234   "Spartan",          "SpartanSE",       "SpartanMM",
00235   "SybylMol",         "SybylMol2",       "Conjure",
00236   "UniChemXYZ",       "XYZ",             "XED", 
00237   0
00238 };
00239 
00240 
00241 /*
00242  * Open Babel 1.100.2 internal file type names
00243  */
00244 static const char *openbabel11filetypes[] = {
00245 "alc",
00246 "prep",
00247 "bs",
00248 "caccrt",
00249 "ccc",
00250 "c3d1",
00251 "c3d2",
00252 "cml",
00253 "crk2d",
00254 "crk3d",
00255 "box",
00256 "dmol",
00257 "feat",
00258 "gam",
00259 "gpr",
00260 "mm1gp",
00261 "qm1gp",
00262 "hin",
00263 "jout",
00264 "bin",
00265 "mmd",
00266 "car",
00267 "sdf",
00268 "mol",
00269 "mopcrt",
00270 "mopout",
00271 "mmads",
00272 "mpqc",
00273 "bgf",
00274 "nwo",
00275 "pqs",
00276 "qcout",
00277 "res",
00278 "smi",
00279 "mol2",
00280 "unixyz",
00281 "vmol",
00282 "xyz",
00283 0
00284 };
00285 
00286 /*
00287  * Plugin names registered in VMD for each Open Babel 1.100.2 file type
00288  */
00289 static const char *openbabel11filetypenames[] = {
00290   "Alchemy",          "AMBERPREP",       "BallStick",      
00291   "Cacao",            "CCC",           
00292   "Chem3d-1",         "Chem3d-2",        "ChemicalMarkup"
00293   "CRK2D",            "CRK3D",           "Dock35Box",
00294   "Dmol3Coord",       "Feature",         "GAMESSoutput",     
00295   "GhemicalProj",     "GhemicalMM",      "GhemicalQM",
00296   "HyperchemHIN",     "JaguarOutput",    "OpenEyeBinary",
00297   "Macromodel",       "BiosymCAR",       "IsisSDF",
00298   "MDLMOL",           "MopacCartesian",  "MopacOutput",     
00299   "MMADS",            "MPQC",            "MSIBGF",  
00300   "NWChemOutput",     "PQS",             "QChemOutput",
00301   "ShelX",            "SMILES",          "SybylMol2",   
00302   "UniChemXYZ",       "ViewMol",         "XYZ",
00303   0
00304 };
00305 
00306 
00307 static const char *babel16type_from_name(const char *name) {
00308   const char **ptr = babel16filetypenames;
00309   int i=0; 
00310   while (*ptr) {
00311     if (!strcmp(*ptr, name))
00312       return babel16filetypes[i];
00313     ptr++;
00314     i++;
00315   }
00316   return NULL;
00317 }
00318 
00319 static const char *openbabel11type_from_name(const char *name) {
00320   const char **ptr = openbabel11filetypenames;
00321   int i=0; 
00322   while (*ptr) {
00323     if (!strcmp(*ptr, name))
00324       return openbabel11filetypes[i];
00325     ptr++;
00326     i++;
00327   }
00328   return NULL;
00329 }
00330 
00331 
00332 /* 
00333  * Figure out the file type, call babel, and return a handle if successful.
00334  * From this point we're just reading in a pdb file.
00335  */
00336 static void *open_babel_read(const char *filename, const char *filetypename,
00337     int *natoms) {
00338 
00339   const char *babelbin;
00340   char *current_file;
00341   pdbdata *pdb;
00342   char *s;
00343   const char *fmt;
00344   int count = 0;
00345   VMDDIR *dirp;
00346   char *dp;
00347   char temps[100];
00348   char tempc;
00349   char lastc;
00350   int may_have_multi = 0;
00351   char *tmp_multi = NULL;
00352   const char *filetype;
00353 
00354   babelbin = getenv("VMDBABELBIN");
00355   if (!babelbin) {
00356     fprintf(stderr, "Babel plugin needs VMDBABELBIN environment variable\n"
00357                     "to point to location of Babel executable\n");
00358     return NULL;
00359   }
00360 
00361 #if 0
00362   /* Try Open Babel file type names first... */ 
00363   filetype = openbabel11type_from_name(filetypename);
00364   if (!filetype) {
00365     fprintf(stderr, "No Open Babel 1.100.2 file type for '%s'\n", filetypename);
00366   }
00367 #endif
00368 
00369   /* Try Babel 1.6 file type names if Open Babel didn't match */ 
00370   filetype = babel16type_from_name(filetypename);
00371   if (!filetype) {
00372     fprintf(stderr, "No Babel 1.6 file type for '%s'\n", filetypename);
00373     return NULL;
00374   }
00375   s = (char *)malloc(strlen(babelbin) +               
00376               strlen(" -i       -opdb ") +
00377               strlen(filename) +
00378               strlen(file(filename, 0, 1)) +
00379               20);
00380  
00381   /*
00382   // On windows its necessary to quote command names due to
00383   // the high tendency for paths to have spaces in them.
00384   */
00385   sprintf(s, "\"%s\" -i%s \"%s\" all -opdb \"%s\"",
00386      babelbin, filetype, filename, (const char *)file(filename, 0, 0));
00387 
00388   delete_all(filename);       /* delete any conflicting existing files  */
00389   system(s);                  /* run the babel command                  */
00390   free(s);
00391 
00392   /* now find how many frames were printed */
00393   fmt = file(filename, 0, -2);
00394   dirp = vmd_opendir(BABEL_TMPDIR);
00395   if (dirp == NULL) {
00396     return NULL; /* failure */
00397   }
00398  
00399    lastc = *(filename + strlen(filename) -1);
00400 
00401    while ((dp = vmd_readdir(dirp)) != NULL) {
00402       if (sscanf(dp, fmt, temps, &tempc) > 1 && lastc == tempc) {
00403      count++;
00404      /* check if there is 1 element but Babel thinks there are several */
00405      if (count == 1) {
00406         if (strstr(dp, "0001.")) {
00407            may_have_multi = 1;
00408            tmp_multi = strdup(dp);
00409         }
00410      }
00411       }
00412    }
00413    vmd_closedir(dirp);
00414 
00415    if (may_have_multi && count == 1) {
00416       /* then move the test0001.extension file to test.extension */
00417       char *s2, *t2;
00418       s2 = (char *)malloc(2*(strlen(tmp_multi)+strlen(BABEL_TMPDIR))+40);
00419 
00420 #if defined(_MSC_VER)
00421       sprintf(s2, "move \"%s\\%s\" \"%s\\\"", BABEL_TMPDIR, tmp_multi, BABEL_TMPDIR);
00422 #else
00423       sprintf(s2, "mv \"%s/%s\" \"%s/\"", BABEL_TMPDIR, tmp_multi, BABEL_TMPDIR);
00424 #endif
00425 
00426       t2 = strstr(tmp_multi, "0001.");
00427       *t2 = 0;
00428       strcat(s2, tmp_multi);
00429       strcat(s2, t2 + 4);
00430       fprintf(stderr, "%s\n", s2);
00431       system(s2);
00432       free(s2);
00433    }
00434 
00435    if (tmp_multi) {
00436       free(tmp_multi);
00437    }
00438 
00439   /*
00440    * Ok, now that we're done with all that crap, we should have a bunch
00441    * of temp files.  Now we need to open the first one to get the
00442    * number of atoms.
00443    */
00444   if (count == 0) {
00445     fprintf(stderr, "Babel molecule file translation failed!\n");
00446     return NULL;
00447   }
00448   current_file = file(filename, 0, count > 1);
00449   pdb = open_pdb_read(current_file, natoms);
00450   if (!pdb) {
00451     fprintf(stderr, "Couldn't read structure from Babel pdb output\n");
00452     free(current_file);
00453     return NULL;
00454   }
00455   pdb->original_file = strdup(filename); 
00456   pdb->current_file = current_file;
00457   pdb->babel_num = count;
00458   pdb->babel_i = 1;
00459   return pdb;
00460 }
00461 
00462 static int read_pdb_structure(void *mydata, int *optflags, 
00463     molfile_atom_t *atoms) {
00464   pdbdata *pdb = (pdbdata *)mydata;
00465   molfile_atom_t *atom;
00466   char pdbrec[PDB_BUFFER_LENGTH];
00467   int i, rectype, atomserial, pteidx;
00468   char ridstr[8];
00469   char elementsymbol[3];
00470   int badptecount = 0;
00471   long fpos = ftell(pdb->fd);
00472  
00473   *optflags = MOLFILE_INSERTION | MOLFILE_OCCUPANCY | MOLFILE_BFACTOR | 
00474               MOLFILE_ALTLOC | MOLFILE_ATOMICNUMBER;
00475 
00476   i = 0;
00477   do {
00478     rectype = read_pdb_record(pdb->fd, pdbrec);
00479     switch (rectype) {
00480     case PDB_ATOM:
00481       atom = atoms+i;
00482       get_pdb_fields(pdbrec, strlen(pdbrec), &atomserial,
00483           atom->name, atom->resname, atom->chain, atom->segid, 
00484           ridstr, atom->insertion, atom->altloc, elementsymbol,
00485           NULL, NULL, NULL, &atom->occupancy, &atom->bfactor);
00486       atom->resid = atoi(ridstr);
00487 
00488       /* determine atomic number from the element symbol */
00489       pteidx = get_pte_idx_from_string(elementsymbol);
00490       atom->atomicnumber = pteidx;
00491       if (pteidx != 0) {
00492         atom->mass = get_pte_mass(pteidx);
00493         atom->radius = get_pte_vdw_radius(pteidx);
00494       } else {
00495         badptecount++; /* unrecognized element */
00496       }
00497       strcpy(atom->type, atom->name);
00498       i++;
00499       break;
00500     default:
00501       break;
00502     }
00503   } while (rectype != PDB_END && rectype != PDB_EOF);
00504 
00505   fseek(pdb->fd, fpos, SEEK_SET);
00506 
00507   /* if all atoms are recognized, set the mass and radius flags too,  */
00508   /* otherwise let VMD guess these for itself using it's own methods  */
00509   if (badptecount == 0) {
00510     *optflags |= MOLFILE_MASS | MOLFILE_RADIUS;
00511   }
00512 
00513   return MOLFILE_SUCCESS;
00514 }
00515 
00516 static int read_next_timestep(void *v, int natoms, molfile_timestep_t *ts) {
00517   pdbdata *pdb = (pdbdata *)v;
00518   char pdbstr[PDB_BUFFER_LENGTH];
00519   int indx, i;
00520   float *x, *y, *z;
00521   float occup[1], beta[1];
00522   if (ts) {
00523     x = ts->coords;
00524     y = x+1;
00525     z = x+2;
00526   } else {
00527     x = y = z = 0;
00528   }
00529   i = 0;
00530   if (!pdb->fd) 
00531     return MOLFILE_ERROR;
00532 
00533   /* Read the rest of the frames in the current fd.  If there aren't any
00534    * more close it and go on to the next one.  If there aren't any more frames,
00535    * return MOLFILE_ERROR (-1);
00536    */
00537   
00538   while (i < pdb->natoms) {
00539     indx = read_pdb_record(pdb->fd, pdbstr);
00540     if(indx == PDB_ATOM) {
00541       /* just get the coordinates, and store them */
00542       if (ts) {
00543         get_pdb_coordinates(pdbstr, x, y, z, occup, beta);
00544         x += 3;
00545         y += 3;
00546         z += 3;
00547         i++;
00548       }
00549     } else if (indx == PDB_CRYST1) {
00550       if (ts) {
00551         get_pdb_cryst1(pdbstr, &ts->alpha, &ts->beta, &ts->gamma,
00552                                &ts->A, &ts->B, &ts->C);
00553       }
00554     } else if (indx == PDB_EOF) {
00555       if (i == 0) {
00556         /* Need to start a new frame, if possible */
00557         fclose(pdb->fd);
00558         pdb->fd = 0;
00559         vmd_delete_file(pdb->current_file);
00560         free(pdb->current_file);
00561         pdb->current_file = 0;
00562         pdb->babel_i++;
00563         if (pdb->babel_i >= pdb->babel_num) 
00564           return MOLFILE_ERROR; 
00565         pdb->current_file = file(pdb->original_file, pdb->babel_i, pdb->babel_num > 1); 
00566         pdb->fd = fopen(pdb->current_file, "r");
00567         if (!pdb->fd) {
00568           fprintf(stderr, 
00569             "Couldn't read babel output file %s\n", pdb->current_file); 
00570           free(pdb->current_file);
00571           pdb->current_file = 0;
00572           return MOLFILE_ERROR; 
00573         } 
00574       } else {
00575         /* premature end */
00576         fprintf(stderr, "PDB file %s contained too few atoms\n", pdb->current_file);
00577         return MOLFILE_ERROR;
00578       }
00579     }
00580   }
00581 
00582   return MOLFILE_SUCCESS; 
00583 }
00584 
00585 /* 
00586  * Free the pdb handle, and delete all the babel temp files.
00587  */
00588 static void close_pdb_read(void *v) {
00589   pdbdata *pdb = (pdbdata *)v;
00590   if (!pdb) return;
00591   if (pdb->fd) {
00592     fclose(pdb->fd);
00593     pdb->fd = 0;
00594     vmd_delete_file(pdb->current_file);
00595     free(pdb->current_file);
00596   }
00597   free(pdb);
00598 }
00599 
00600 
00601 
00602 /*
00603  * Initialization stuff down here
00604  */
00605 
00606 static molfile_plugin_t *plugins;
00607 static int nplugins;
00608 
00609 VMDPLUGIN_API int VMDPLUGIN_init() {
00610 #if defined(_MSC_VER)
00611   return VMDPLUGIN_SUCCESS;
00612 #else
00613   /* register all Babel 1.6 conversion options */
00614   const char **s = babel16filetypenames;
00615   int i;
00616   nplugins = 0;
00617   while (*s) { nplugins++; s++; }
00618   plugins = (molfile_plugin_t*)calloc(nplugins, sizeof(molfile_plugin_t));
00619   for (i=0; i<nplugins; i++) {
00620     plugins[i].abiversion = vmdplugin_ABIVERSION;         /* ABI version */
00621     plugins[i].type = MOLFILE_CONVERTER_PLUGIN_TYPE;      /* type of plugin */
00622     plugins[i].name = babel16filetypenames[i];            /* name of plugin */
00623     plugins[i].prettyname = babel16filetypenames[i];      /* name of plugin */
00624     plugins[i].author = "Justin Gullingsrud, John Stone"; /* author */
00625     plugins[i].majorv = 1;                                /* major version */
00626     plugins[i].minorv = 13;                               /* minor version */
00627     plugins[i].is_reentrant = VMDPLUGIN_THREADUNSAFE;     /* is not reentrant */
00628     plugins[i].filename_extension = babel16filetypes[i];  /* file extension */
00629     plugins[i].open_file_read = open_babel_read;
00630     plugins[i].read_structure = read_pdb_structure;
00631     plugins[i].read_next_timestep = read_next_timestep;
00632     plugins[i].close_file_read = close_pdb_read;
00633   }
00634 
00635 #if 0
00636   /* register all Open Babel 1.100.2 conversion options */
00637   const char **s = openbabel11filetypenames;
00638   int i;
00639   nplugins = 0;
00640   while (*s) { nplugins++; s++; }
00641   plugins = (molfile_plugin_t*)calloc(nplugins, sizeof(molfile_plugin_t));
00642   for (i=0; i<nplugins; i++) {
00643     plugins[i].abiversion = vmdplugin_ABIVERSION;         /* ABI version */
00644     plugins[i].type = MOLFILE_CONVERTER_PLUGIN_TYPE;      /* type of plugin */
00645     plugins[i].shortname = openbabel11filetypenames[i];   /* name of plugin */
00646     plugins[i].prettyname = openbabel11filetypenames[i];  /* name of plugin */
00647     plugins[i].author = "Justin Gullingsrud, John Stone"; /* author */
00648     plugins[i].majorv = 2;                                /* major version */
00649     plugins[i].minorv = 12;                               /* minor version */
00650     plugins[i].is_reentrant = VMDPLUGIN_THREADUNSAFE;     /* is not reentrant */
00651     plugins[i].filename_extension = openbabel11filetypes[i];  /* file extension */
00652     plugins[i].open_file_read = open_babel_read;
00653     plugins[i].read_structure = read_pdb_structure;
00654     plugins[i].read_next_timestep = read_next_timestep;
00655     plugins[i].close_file_read = close_pdb_read;
00656   }
00657 #endif
00658 
00659   return VMDPLUGIN_SUCCESS;
00660 #endif
00661 }
00662 
00663 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00664 #if defined(_MSC_VER)
00665   return VMDPLUGIN_SUCCESS;
00666 #else
00667   int i;
00668   for (i=0; i<nplugins; i++) {
00669     (*cb)(v, (vmdplugin_t *)(plugins+i));
00670   }
00671   return VMDPLUGIN_SUCCESS;
00672 #endif
00673 }
00674 
00675 VMDPLUGIN_API int VMDPLUGIN_fini() {
00676 #if defined(_MSC_VER)
00677   return VMDPLUGIN_SUCCESS;
00678 #else
00679   free(plugins);
00680   nplugins = 0;
00681   plugins = 0;
00682   return VMDPLUGIN_SUCCESS;
00683 #endif
00684 }
00685 
00686 
00687 #ifdef TEST_BABEL_PLUGIN
00688 
00689 int main(int argc, char *argv[]) {
00690   molfile_header_t header;
00691   molfile_timestep_t timestep;
00692   void *v;
00693 
00694   while (--argc) {
00695     ++argv;
00696     v = open_babel_read(*argv, "xyz", &header);
00697     if (!v) {
00698       fprintf(stderr, "open_babel_read failed for file %s\n", *argv);
00699       return 1;
00700     }
00701     timestep.coords = (float *)malloc(3*sizeof(float)*header.numatoms);
00702     while (!read_next_timestep(v, &timestep));
00703     close_pdb_read(v);
00704   }
00705   return 0;
00706 }
00707 
00708 
00709 #endif
00710 
00711 

Generated on Thu Apr 18 03:09:34 2024 for VMD Plugins (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002