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

cubeplugin.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2009 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: cubeplugin.C,v $
00013  *      $Author: akohlmey $       $Locker:  $             $State: Exp $
00014  *      $Revision: 1.29 $       $Date: 2009/05/19 20:33:46 $
00015  *
00016  ***************************************************************************/
00017 
00018 //
00019 // Plugin reader for Gaussian "cube" files
00020 //
00021 // Gaussian "cube" file format described here:
00022 //   http://www.gaussian.com/00000430.htm
00023 //
00024 
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <math.h>
00028 #include <string.h>
00029 
00030 #include "molfile_plugin.h"
00031 #include "unit_conversion.h"
00032 
00033 #ifndef M_PI_2
00034 #define M_PI_2 1.57079632679489661922
00035 #endif
00036 
00037 #include "periodic_table.h"
00038 
00039 #define THISPLUGIN plugin
00040 #include "vmdconio.h"
00041 
00042 static const float bohr = BOHR_TO_ANGS;
00043 
00044 // A format-independent structure to hold unit cell data
00045 typedef struct {
00046   float A, B, C, alpha, beta, gamma;
00047 } cube_box;
00048 
00049 typedef struct {
00050   FILE *fd;              // file descriptor
00051   int nsets;             // number of volume datasets
00052   int numatoms;          // number of atoms
00053   bool coord;            // has coordinate data
00054   long crdpos, datapos;  // seek offsets for coords and data
00055   char *file_name;       // original filename 
00056   float *datacache;      // temporary cache of orbital data prior to conversion
00057   molfile_volumetric_t *vol; // volume data
00058   float origin[3];       // origin, stored for periodic display hack 
00059   float rotmat[3][3];    // rotation matrix, stored for periodic display hack
00060   cube_box box;          // unit cell dimensions
00061 } cube_t;
00062 
00063 // Converts box basis vectors to A, B, C, alpha, beta, and gamma.  
00064 // Stores values in cube_box struct, which should be allocated before calling
00065 // this function.
00066 static int cube_readbox(cube_box *box, float *x, float *y, float *z) {
00067   float A, B, C;
00068 
00069   if (!box) {
00070     return 1;
00071   }
00072 
00073   // provide defaults
00074   box->A = 10.0;
00075   box->B = 10.0;
00076   box->C = 10.0;
00077   box->alpha = 90.0;
00078   box->beta  = 90.0;
00079   box->gamma = 90.0;
00080 
00081   // A, B, C are the lengths of the x, y, z vectors, respectively
00082   A = sqrt( x[0]*x[0] + x[1]*x[1] + x[2]*x[2] );
00083   B = sqrt( y[0]*y[0] + y[1]*y[1] + y[2]*y[2] );
00084   C = sqrt( z[0]*z[0] + z[1]*z[1] + z[2]*z[2] );
00085   if ((A<=0) || (B<=0) || (C<=0)) {
00086     return 1;
00087   }
00088   box->A = A;
00089   box->B = B;
00090   box->C = C;
00091 
00092   // gamma, beta, alpha are the angles between the x & y, x & z, y & z
00093   // vectors, respectively
00094   box->gamma = acos( (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])/(A*B) ) * 90.0/M_PI_2;
00095   box->beta = acos( (x[0]*z[0]+x[1]*z[1]+x[2]*z[2])/(A*C) ) * 90.0/M_PI_2;
00096   box->alpha = acos( (y[0]*z[0]+y[1]*z[1]+y[2]*z[2])/(B*C) ) * 90.0/M_PI_2; 
00097 
00098   return 0;
00099 }
00100 
00101 // calculate and store origin and rotation matrix to realign everything later.
00102 static void cube_buildrotmat(cube_t *cube, float *o, float *a, float *b)
00103 {
00104   // we rotate first around y and z to align a along the x-axis...
00105   const double len   = sqrt(a[0]*a[0] + a[1]*a[1]);
00106   const double phi   = atan2((double) a[2], (double) len);
00107   const double theta = atan2((double) a[1], (double) a[0]);
00108 
00109   const double cph = cos(phi);
00110   const double cth = cos(theta);
00111   const double sph = sin(phi);
00112   const double sth = sin(theta);
00113 
00114   // ...then we rotate around x to put b into the xy-plane.
00115   const double psi = atan2(-sph*cth*b[0] - sph*sth*b[1] + cph*b[2],-sth*b[0] + cth*b[1]);
00116   const double cps = cos(psi);
00117   const double sps = sin(psi);
00118 
00119   const double r[3][3] = { 
00120     {               cph*cth,                    cph*sth,      sph},
00121     {-sth*cps - sph*cth*sps,      cth*cps - sph*sth*sps,  cph*sps},
00122     { sth*sps - sph*cth*cps,     -cth*sps - sph*sth*cps,  cph*cps}
00123   };
00124 
00125   for (int i=0; i<3; ++i) {
00126     cube->origin[i] = o[i];
00127     for (int j=0; j<3; ++j) {
00128       cube->rotmat[i][j] = r[i][j];
00129     }
00130   }
00131 }
00132 
00133 
00134 static void eatline(FILE * fd) {
00135   char readbuf[1025];
00136   fgets(readbuf, 1024, fd);    // go on to next line
00137 }  
00138 
00139 // prototype.
00140 static void close_cube_read(void *v);
00141 
00142 static void *open_cube_read(const char *filepath, const char *filetype,
00143     int *natoms) {
00144   FILE *fd;
00145   cube_t *cube;
00146   int xsize, ysize, zsize;
00147   float a[3], b[3], c[3];
00148   int i;
00149  
00150   fd = fopen(filepath, "rb");
00151   if (!fd) 
00152     return NULL;
00153 
00154   cube = new cube_t;
00155   cube->fd = fd;
00156   cube->vol = NULL;
00157   cube->coord = false;
00158   cube->file_name = strdup(filepath);
00159   cube->datacache = NULL;
00160 
00161   // initialize origin and rotmat to sensible defaults.
00162   for (i=0; i<3; ++i) {
00163       for (int j=0; j<3; ++j) {
00164           cube->rotmat[i][j] = 0.0;
00165       }
00166   }
00167   for (i=0; i<3; ++i) {
00168       cube->origin[i] = 0.0;
00169       cube->rotmat[i][i] = 1.0;
00170   }
00171 
00172   molfile_volumetric_t voltmpl; // base information for all data sets.
00173 
00174   // read in cube file header information
00175   char readbuf[256]; 
00176   fgets(readbuf, 256, cube->fd);    // go on to next line
00177 
00178   // identify this file, and read title string into dataset info
00179   strcpy(voltmpl.dataname, "Gaussian Cube: ");
00180   strncat(voltmpl.dataname, readbuf, 240);      // 240 is max space left after
00181                                                 //   "Gaussian Cube: "
00182   eatline(cube->fd);          // skip second header line 
00183 
00184   // read in number of atoms
00185   if (fscanf(cube->fd, "%d", &cube->numatoms) != 1) {
00186     close_cube_read(cube);
00187     return NULL;
00188   }
00189 
00190   if (cube->numatoms > 0) {   // density cube file
00191     cube->nsets = 1;          // this cube file contains only one data set
00192   } else {
00193     // cube file with orbitals => multiple densities.
00194     cube->numatoms = - cube->numatoms;
00195     cube->nsets = 0;          // we don't know yet how many data sets.
00196   }
00197   *natoms = cube->numatoms;
00198 
00199   // read in cube origin
00200   if ( fscanf(cube->fd, "%f %f %f", 
00201          &voltmpl.origin[0], 
00202          &voltmpl.origin[1], 
00203          &voltmpl.origin[2]) != 3 ) {
00204     close_cube_read(cube);
00205     return NULL;
00206   }
00207 
00208   // read in cube axes and sizes
00209   if ((fscanf(cube->fd, "%d", &xsize) != 1) ||
00210       (fscanf(cube->fd, "%f %f %f", &a[0], &a[1], &a[2]) != 3)) {
00211     close_cube_read(cube);
00212     return NULL;
00213   }
00214 
00215   if ((fscanf(cube->fd, "%d", &ysize) != 1) ||
00216       (fscanf(cube->fd, "%f %f %f", &b[0], &b[1], &b[2]) != 3)) {
00217     close_cube_read(cube);
00218     return NULL;
00219   }
00220 
00221   if ((fscanf(cube->fd, "%d", &zsize) != 1) ||
00222       (fscanf(cube->fd, "%f %f %f", &c[0], &c[1], &c[2]) != 3)) {
00223     close_cube_read(cube);
00224     return NULL;
00225   }
00226 
00227   // calculate number of samples in each dimension
00228   voltmpl.xsize = xsize;
00229   voltmpl.ysize = ysize;
00230   voltmpl.zsize = zsize;
00231   voltmpl.has_color = 0;
00232 
00233   eatline(cube->fd);     // skip remaining end of line characters
00234 
00235   // to make the periodic display work, we need to rotate
00236   // the cellvectors (and the coordinates) in such a way,
00237   // that the a-vector is collinear with the x-axis and
00238   // the b-vector is in the xy-plane. 
00239   cube_buildrotmat(cube, voltmpl.origin, a, b);
00240   // print warning, if the rotation will be significant:
00241   if ((fabs((double) a[1]) + fabs((double) a[2]) + fabs((double) b[2]))
00242       > 0.001) {
00243     vmdcon_printf(VMDCON_WARN, 
00244             "cubeplugin) Coordinates will be rotated to comply \n");
00245     vmdcon_printf(VMDCON_WARN, 
00246             "cubeplugin) with VMD's conventions for periodic display.\n");
00247   }
00248 
00249   // all dimensional units are always in Bohr
00250   // so scale axes and origin correctly.
00251   // NOTE: the angstroms are only allowed in input.
00252   voltmpl.origin[0] *= bohr; 
00253   voltmpl.origin[1] *= bohr;
00254   voltmpl.origin[2] *= bohr;
00255 
00256   // store aligned axes.
00257   for (i=0; i<3; ++i) {
00258     voltmpl.xaxis[i] = cube->rotmat[i][0] * a[0] 
00259       + cube->rotmat[i][1] * a[1] + cube->rotmat[i][2] * a[2];
00260 
00261     voltmpl.yaxis[i] = cube->rotmat[i][0] * b[0] 
00262       + cube->rotmat[i][1] * b[1] + cube->rotmat[i][2] * b[2];
00263     
00264     voltmpl.zaxis[i] = cube->rotmat[i][0] * c[0] 
00265       + cube->rotmat[i][1] * c[1] + cube->rotmat[i][2] * c[2];
00266   }
00267 
00268   voltmpl.xaxis[0] *= bohr * xsize;
00269   voltmpl.xaxis[1] *= bohr * xsize; 
00270   voltmpl.xaxis[2] *= bohr * xsize; 
00271 
00272   voltmpl.yaxis[0] *= bohr * ysize; 
00273   voltmpl.yaxis[1] *= bohr * ysize; 
00274   voltmpl.yaxis[2] *= bohr * ysize; 
00275 
00276   voltmpl.zaxis[0] *= bohr * zsize; 
00277   voltmpl.zaxis[1] *= bohr * zsize; 
00278   voltmpl.zaxis[2] *= bohr * zsize; 
00279 
00280 #if 1
00281   /*   As of VMD version 1.8.3, volumetric data points are 
00282    *   expected to represent the center of a grid box. cube format 
00283    *   volumetric data represents the value at the edges of the 
00284    *   grid boxes, so we need to shift the internal origin by half
00285    *   a grid box diagonal to have the data at the correct position.
00286    *   This will need to be changed again when the plugin interface 
00287    *   is updated to explicitly allow point/face-centered data sets.
00288    */
00289   voltmpl.origin[0] -= 0.5 * ( voltmpl.xaxis[0] / (double) xsize
00290                         + voltmpl.yaxis[0] / (double) ysize
00291                         + voltmpl.zaxis[0] / (double) zsize);
00292   voltmpl.origin[1] -= 0.5 * ( voltmpl.xaxis[1] / (double) xsize
00293                         + voltmpl.yaxis[1] / (double) ysize
00294                         + voltmpl.zaxis[1] / (double) zsize);
00295   voltmpl.origin[2] -= 0.5 * ( voltmpl.xaxis[2] / (double) xsize
00296                         + voltmpl.yaxis[2] / (double) ysize
00297                         + voltmpl.zaxis[2] / (double) zsize);
00298 #endif
00299 
00300 #if defined(TEST_PLUGIN)
00301   printf("cell before rotation:\n");
00302   printf("a: %12.8f %12.8f %12.8f\n", a[0]*xsize*bohr, a[1]*ysize*bohr, a[2]*zsize*bohr);
00303   printf("b: %12.8f %12.8f %12.8f\n", b[0]*xsize*bohr, b[1]*ysize*bohr, b[2]*zsize*bohr);
00304   printf("c: %12.8f %12.8f %12.8f\n", c[0]*xsize*bohr, c[1]*ysize*bohr, c[2]*zsize*bohr);
00305 
00306   printf("cell after rotation:\n");
00307   printf("x: %12.8f %12.8f %12.8f\n", voltmpl.xaxis[0], voltmpl.xaxis[1], voltmpl.xaxis[2]);
00308   printf("y: %12.8f %12.8f %12.8f\n", voltmpl.yaxis[0], voltmpl.yaxis[1], voltmpl.yaxis[2]);
00309   printf("z: %12.8f %12.8f %12.8f\n", voltmpl.zaxis[0], voltmpl.zaxis[1], voltmpl.zaxis[2]);
00310 #endif
00311 
00312   // store the unit cell information for later perusal.
00313   if (cube_readbox(&(cube->box), voltmpl.xaxis, voltmpl.yaxis, voltmpl.zaxis)) {
00314           vmdcon_printf(VMDCON_WARN, "cubeplugin) Calculation of unit cell "
00315                                      "size failed. Continuing anyways...\n");
00316   }
00317 
00318   cube->crdpos = ftell(cube->fd); // and record beginning of coordinates
00319   // XXX fseek()/ftell() are incompatible with 64-bit LFS I/O implementations, 
00320   // hope we don't read any files >= 2GB...
00321 
00322   if (cube->nsets >0) { 
00323     int i;
00324 
00325     // density cube file, copy voltmpl into the cube struct.
00326     cube->vol = new molfile_volumetric_t[1];
00327     memcpy(cube->vol, &voltmpl, sizeof(voltmpl));
00328 
00329     // skip over coordinates to find the start of volumetric data
00330     for (i=0; i < cube->numatoms; i++) {
00331       eatline(cube->fd);
00332     }
00333 
00334     cube->datapos = ftell(cube->fd); // and record beginning of data
00335     // XXX fseek()/ftell() are incompatible with 64-bit LFS I/O, 
00336     // hope we don't read any files >= 2GB...
00337   } else {              
00338     int i;
00339 
00340     // orbital cube file. we now have to read the orbitals section
00341     // skip over coordinates
00342     for (i=0; i < cube->numatoms; i++) {
00343       eatline(cube->fd);
00344     }
00345       
00346     fscanf(cube->fd, "%d", &cube->nsets);
00347     vmdcon_printf(VMDCON_INFO, "cubeplugin) found %d orbitals\n", cube->nsets);
00348     cube->vol = new molfile_volumetric_t[cube->nsets];
00349     for (i=0; i < cube->nsets; ++i) {
00350       int orb;
00351       fscanf(cube->fd, "%d", &orb);
00352       memcpy(&cube->vol[i], &voltmpl, sizeof(voltmpl));
00353       sprintf(cube->vol[i].dataname, "Gaussian Cube: Orbital %d", orb);
00354     }
00355       
00356     eatline(cube->fd);        // gobble up rest of line
00357     cube->datapos = ftell(cube->fd); // and record beginning of data
00358     // XXX fseek()/ftell() are incompatible with 64-bit LFS I/O, 
00359     // hope we don't read any files >= 2GB...
00360   }
00361 
00362   return cube;
00363 }
00364 
00365   
00366 static int read_cube_structure(void *v, int *optflags, molfile_atom_t *atoms) {
00367   int i, j;
00368   char *k;
00369   molfile_atom_t *atom;
00370 
00371   cube_t *cube = (cube_t *)v;
00372 
00373   // go to coordinates
00374   fseek(cube->fd, cube->crdpos, SEEK_SET);
00375   // XXX fseek()/ftell() are incompatible with 64-bit LFS I/O implementations, 
00376   // hope we don't read any files >= 2GB...
00377 
00378   /* set mass and radius from PTE, charge from atoms section of cube file. */
00379   *optflags = MOLFILE_ATOMICNUMBER | MOLFILE_MASS | MOLFILE_RADIUS | MOLFILE_CHARGE; 
00380 
00381   for(i=0;i<cube->numatoms;i++) {
00382     int idx;
00383     float chrg;
00384     char fbuffer[1024];
00385 
00386     atom = atoms + i;
00387 
00388     k = fgets(fbuffer, 1024, cube->fd);
00389     j=sscanf(fbuffer, "%d %f %*f %*f %*f", &idx, &chrg);
00390     if (k == NULL) {
00391       vmdcon_printf(VMDCON_ERROR, "cube structure) missing atom(s) in "
00392                                   "file '%s'\n",cube->file_name);
00393       vmdcon_printf(VMDCON_ERROR, "cube structure) expecting '%d' atoms,"
00394                                   " found only '%d'\n",cube->numatoms,i+1);
00395       return MOLFILE_ERROR;
00396     } else if (j < 2) {
00397       vmdcon_printf(VMDCON_INFO, "cube structure) missing atom data in file"
00398                                  " '%s' for atom '%d'\n",cube->file_name,i+1);
00399       return MOLFILE_ERROR;
00400     }
00401 
00402     // assign atom symbol to number. flag unknown or dummy atoms with X.
00403     atom->atomicnumber = idx;
00404     strncpy(atom->name, get_pte_label(idx), sizeof(atom->name));
00405     strncpy(atom->type, atom->name, sizeof(atom->type));
00406     atom->mass = get_pte_mass(idx);
00407     atom->radius = get_pte_vdw_radius(idx);
00408     atom->resname[0] = '\0';
00409     atom->resid = 1;
00410     atom->chain[0] = '\0';
00411     atom->segid[0] = '\0';
00412     atom->charge = chrg;
00413     /* skip to the end of line */
00414   }
00415 
00416   return MOLFILE_SUCCESS;
00417 }
00418 
00419 
00420 static int read_cube_timestep(void *v, int natoms, molfile_timestep_t *ts) {
00421   int i, j, n;
00422   char fbuffer[1024];
00423   float x, y, z;
00424   char *k;
00425   
00426   cube_t *cube = (cube_t *)v;
00427 
00428   // there is only one set of coordinates
00429   if (cube->coord) return MOLFILE_EOF;
00430   cube->coord = true;
00431 
00432   // jump to coordinate position
00433   fseek(cube->fd, cube->crdpos, SEEK_SET);
00434   // XXX fseek()/ftell() are incompatible with 64-bit LFS I/O implementations, 
00435   // hope we don't read any files >= 2GB...
00436  
00437   /* read the coordinates */
00438   for (i=0; i<cube->numatoms; i++) {
00439     k = fgets(fbuffer, 1024, cube->fd);
00440     j = sscanf(fbuffer, "%*d %*f %f %f %f", &x, &y, &z);
00441     
00442     if (k == NULL) {
00443       return MOLFILE_ERROR;
00444     } else if (j < 3) {
00445       vmdcon_printf(VMDCON_ERROR, "cube timestep) missing type or coordinate(s)"
00446                     " in file '%s' for atom '%d'\n",cube->file_name,i+1);
00447       return MOLFILE_ERROR;
00448     } else if (j>=3) {
00449       if (ts != NULL) { 
00450         // Only save coords if we're given a timestep pointer, 
00451         // otherwise assume that VMD wants us to skip past it.
00452         
00453         // In order to make the periodic display work, we need to
00454         // rotate the coordinates around the origin by the stored
00455         // rotation matrix. All coordinates are in Bohr, so they
00456         // must be converted to Angstrom, too.
00457         x -= cube->origin[0];
00458         y -= cube->origin[1];
00459         z -= cube->origin[2];
00460         
00461         for (n=0; n<3; ++n) {
00462           ts->coords[3*i + n] = bohr*(cube->origin[n] 
00463                                       + cube->rotmat[n][0] * x
00464                                       + cube->rotmat[n][1] * y
00465                                       + cube->rotmat[n][2] * z);
00466         }
00467       }
00468     } else {
00469       break;
00470     }
00471   }
00472   // set unitcell dimensions from cached data.
00473   if (ts != NULL) { 
00474       ts->A = cube->box.A;
00475       ts->B = cube->box.B;
00476       ts->C = cube->box.C;
00477       ts->alpha = cube->box.alpha;
00478       ts->beta  = cube->box.beta;
00479       ts->gamma = cube->box.gamma;
00480   }
00481   
00482   return MOLFILE_SUCCESS;
00483 }
00484 
00485 static int read_cube_metadata(void *v, int *nsets, 
00486   molfile_volumetric_t **metadata) {
00487   cube_t *cube = (cube_t *)v;
00488   *nsets = cube->nsets; 
00489   *metadata = cube->vol;  
00490 
00491   return MOLFILE_SUCCESS;
00492 }
00493 
00494 static int read_cube_data(void *v, int set, float *datablock, float *colorblock) {
00495   cube_t *cube = (cube_t *)v;
00496 
00497   vmdcon_printf(VMDCON_INFO, "cubeplugin) trying to read cube data set %d\n", set);
00498 
00499   int xsize = cube->vol[set].xsize; 
00500   int ysize = cube->vol[set].ysize;
00501   int zsize = cube->vol[set].zsize;
00502   int xysize = xsize*ysize;
00503   int nsize = cube->nsets;
00504   int nzsize = nsize*zsize;
00505   int nyzsize = nsize*zsize*ysize;
00506   int x, y, z;
00507 
00508   // go to data
00509   fseek(cube->fd, cube->datapos, SEEK_SET);
00510   // XXX fseek()/ftell() are incompatible with 64-bit LFS I/O implementations, 
00511   // hope we don't read any files >= 2GB...
00512 
00513   // read the data values in 
00514   if (cube->nsets == 1) { // density cube file
00515     for (x=0; x<xsize; x++) {
00516       for (y=0; y<ysize; y++) {
00517         for (z=0; z<zsize; z++) {
00518           if (fscanf(cube->fd, "%f", &datablock[z*xysize + y*xsize + x]) != 1) {
00519               return MOLFILE_ERROR;
00520           }
00521         }
00522       } 
00523     }
00524   } else {
00525     // XXX we may wish to examine this strategy for alternatives that provide
00526     // the same performance but without the extra copy, but it makes sense 
00527     // for now.  
00528 
00529     // Since the orbital cube file stores the data orb1(a1,b1,c1), orb2(a1,b1,c1), 
00530     // ... orbn(a1,b1,c1), orb1(a1,b1,c2), orb2(a1,a1,c2), ..., orbn(ai,bj,ck)
00531     // we have to cache the whole data set of have any kind of reasonable performance.
00532     // otherwise we would have to read (and parse!) the whole file over and over again.
00533     // this way we have to do it only once at the temporary expense of some memory.
00534     if (cube->datacache == NULL) {
00535       int points = xsize*ysize*zsize * nsize; // number of grid cells * nsets
00536       int i;
00537 
00538       // let people know what is going on.
00539       vmdcon_printf(VMDCON_INFO, "cubeplugin) creating %d MByte cube orbital"
00540                     " cache.\n", (int) (points*sizeof(float)) / 1048576);
00541       cube->datacache = new float[points];
00542             
00543       for (i=0; i < points; ++i) {
00544         if (fscanf(cube->fd, "%f", &cube->datacache[i]) != 1) {
00545           return MOLFILE_ERROR;
00546         }
00547 
00548         // print an ascii progress bar so impatient people do not get scared.
00549         // this does not translate well with vmdcon, so we keep it.
00550         // we'd need some way to flag replacing a line instead of writing it.
00551         if ((i % (1048576/sizeof(float))) == 0) {  // one dot per MB.
00552           fprintf(stderr, "."); 
00553         }
00554       }
00555     }
00556       
00557     for (x=0; x<xsize; x++) {
00558       for (y=0; y<ysize; y++) {
00559         for (z=0; z<zsize; z++) {
00560           datablock[z*xysize + y*xsize + x] = cube->datacache[x*nyzsize + y*nzsize + z*nsize + set];
00561         }
00562       }
00563     }
00564   }
00565 
00566   return MOLFILE_SUCCESS;
00567 }
00568 
00569 static void close_cube_read(void *v) {
00570   cube_t *cube = (cube_t *)v;
00571 
00572   fclose(cube->fd);
00573   if (cube->vol) {
00574     delete[] cube->vol; 
00575   }
00576   free(cube->file_name);
00577   if (cube->datacache) { 
00578     vmdcon_printf(VMDCON_INFO, "cubeplugin) freeing cube orbital cache.\n");
00579     delete[] cube->datacache; 
00580   }  
00581 
00582   delete cube;
00583 }
00584 
00585 /*
00586  * Initialization stuff here
00587  */
00588 
00589 int VMDPLUGIN_init(void) { 
00590   memset(&plugin, 0, sizeof(molfile_plugin_t));
00591   plugin.abiversion = vmdplugin_ABIVERSION;
00592   plugin.type = MOLFILE_PLUGIN_TYPE;
00593   plugin.name = "cube";
00594   plugin.prettyname = "Gaussian Cube";
00595   plugin.author = "Axel Kohlmeyer, John Stone";
00596   plugin.majorv = 1;
00597   plugin.minorv = 1;
00598   plugin.is_reentrant = VMDPLUGIN_THREADSAFE;
00599   plugin.filename_extension = "cub,cube";
00600   plugin.open_file_read = open_cube_read;
00601   plugin.read_structure = read_cube_structure;
00602   plugin.read_next_timestep = read_cube_timestep;
00603   plugin.close_file_read = close_cube_read;
00604   plugin.read_volumetric_metadata = read_cube_metadata;
00605   plugin.read_volumetric_data = read_cube_data;
00606   return VMDPLUGIN_SUCCESS; 
00607 }
00608 
00609 int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00610   (*cb)(v, (vmdplugin_t *)&plugin);
00611   return VMDPLUGIN_SUCCESS;
00612 }
00613 
00614 int VMDPLUGIN_fini(void) { return VMDPLUGIN_SUCCESS; }
00615 
00616 
00617 
00618 #ifdef TEST_PLUGIN
00619 
00620 int main(int argc, char *argv[]) {
00621   int natoms;
00622   void *v;
00623   int i, nsets, set;
00624   molfile_volumetric_t * meta;
00625 
00626   while (--argc) {
00627     ++argv;
00628     v = open_cube_read(*argv, "cube", &natoms);
00629     if (!v) {
00630       fprintf(stderr, "open_cube_read failed for file %s\n", *argv);
00631       return 1;
00632     }
00633     fprintf(stderr, "open_cube_read succeeded for file %s\n", *argv);
00634 
00635     // try loading the EDM metadata now
00636     if (read_cube_metadata(v, &nsets, &meta)) {
00637       return 1; // failed to load cube file
00638     }
00639     fprintf(stderr, "read_cube_metadata succeeded for file %s\n", *argv);
00640 
00641     for (set=0; set<nsets; set++) {
00642       printf("Loading volume set: %d\n", set);   
00643       
00644       int elements = meta[set].xsize * meta[set].ysize * meta[set].zsize;
00645       printf("   Grid Elements: %d\n", elements);
00646       printf(" Grid dimensions: X: %d Y: %d Z: %d\n", 
00647              meta[set].xsize, meta[set].ysize, meta[set].zsize);
00648 
00649       float * voldata = (float *) malloc(sizeof(float) * elements);
00650       float * coldata = NULL;
00651 
00652       if (meta[set].has_color) {
00653         coldata = (float *) malloc(sizeof(float) * elements * 3);
00654       }
00655 
00656       // try loading the data sets now
00657       if (read_cube_data(v, set, voldata, coldata)) {
00658         return 1; // failed to load cube file
00659       }
00660 
00661       printf("First 6 elements:\n   ");
00662       for (i=0; i<6; i++) {
00663         printf("%g, ", voldata[i]);
00664       }
00665       printf("\n"); 
00666 
00667       printf("Last 6 elements:\n   ");
00668       for (i=elements - 6; i<elements; i++) {
00669         printf("%g, ", voldata[i]);
00670       }
00671       printf("\n"); 
00672     }
00673 
00674     close_cube_read(v);
00675   }
00676   return 0;
00677 }
00678 
00679 #endif

Generated on Fri May 24 02:05:06 2013 for VMD Plugins (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002