00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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>
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
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
00075
00076
00077
00078
00079 static char *file(const char *filename, int idx, int has_multi) {
00080
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
00091
00092
00093
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++) {
00113 *ptr = tolower(*ptr);
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);
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
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
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
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
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
00334
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
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
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
00383
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);
00389 system(s);
00390 free(s);
00391
00392
00393 fmt = file(filename, 0, -2);
00394 dirp = vmd_opendir(BABEL_TMPDIR);
00395 if (dirp == NULL) {
00396 return NULL;
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
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
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
00441
00442
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
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++;
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
00508
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
00534
00535
00536
00537
00538 while (i < pdb->natoms) {
00539 indx = read_pdb_record(pdb->fd, pdbstr);
00540 if(indx == PDB_ATOM) {
00541
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
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
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
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
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
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;
00621 plugins[i].type = MOLFILE_CONVERTER_PLUGIN_TYPE;
00622 plugins[i].name = babel16filetypenames[i];
00623 plugins[i].prettyname = babel16filetypenames[i];
00624 plugins[i].author = "Justin Gullingsrud, John Stone";
00625 plugins[i].majorv = 1;
00626 plugins[i].minorv = 13;
00627 plugins[i].is_reentrant = VMDPLUGIN_THREADUNSAFE;
00628 plugins[i].filename_extension = babel16filetypes[i];
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
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;
00644 plugins[i].type = MOLFILE_CONVERTER_PLUGIN_TYPE;
00645 plugins[i].shortname = openbabel11filetypenames[i];
00646 plugins[i].prettyname = openbabel11filetypenames[i];
00647 plugins[i].author = "Justin Gullingsrud, John Stone";
00648 plugins[i].majorv = 2;
00649 plugins[i].minorv = 12;
00650 plugins[i].is_reentrant = VMDPLUGIN_THREADUNSAFE;
00651 plugins[i].filename_extension = openbabel11filetypes[i];
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, ×tep));
00703 close_pdb_read(v);
00704 }
00705 return 0;
00706 }
00707
00708
00709 #endif
00710
00711