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

jsplugin.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: jsplugin.c,v $
00013  *      $Author: johns $       $Locker:  $             $State: Exp $
00014  *      $Revision: 1.21 $       $Date: 2008/09/02 21:34:54 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   Code for reading and writing John's molecular dynamics trajectory files
00019  *   for I/O performance testing and as a simple example plugin.
00020  *
00021  *   No programs actually use this format, so it's only a test/example code.
00022  *
00023  *   This plugin reads and writes mostly the same data that a DCD file 
00024  *   contains, but the ordering of I/O operations avoids having to do
00025  *   scatter/gather passes on the buffers, so it ends up performing 
00026  *   two to three times faster than the DCD format for the same data set.
00027  *
00028  *   Best measured I/O performance in VMD so far is 631 MB/sec on a Sun V880z 
00029  *   Best standalone I/O performance so far is 688 MB/sec.
00030  *
00031  *  Standalone test binary compilation flags:
00032  *  cc -fast -xarch=v9a -I../../include -DTEST_JSPLUGIN jsplugin.c \
00033  *    -o ~/bin/readjs -lm
00034  *
00035  *  Profiling flags:
00036  *  cc -xpg -fast -xarch=v9a -g -I../../include -DTEST_JSPLUGIN jsplugin.c \
00037  *    -o ~/bin/readjs -lm
00038  *
00039  ***************************************************************************/
00040 
00041 #include "largefiles.h"   /* platform dependent 64-bit file I/O defines */
00042 
00043 #include <sys/stat.h>
00044 #include <sys/types.h>
00045 #include <stdio.h>
00046 #include <stdlib.h>
00047 #include <string.h>
00048 #include <math.h>
00049 
00050 #define VMDPLUGIN_STATIC
00051 #include "hash.h"
00052 #include "fastio.h"
00053 #include "endianswap.h"
00054 #include "molfile_plugin.h"
00055 
00056 #ifndef M_PI_2
00057 #define M_PI_2 1.57079632679489661922
00058 #endif
00059 
00060 #define JSHEADERSTRING   "JS Binary Structure and Trajectory File Format"                
00061 #define JSMAGICNUMBER    0x31337
00062 #define JSENDIANISM      0x12345678
00063 #if 0
00064 #define JSMAJORVERSION   2
00065 #define JSMINORVERSION   0
00066 #else
00067 #define JSMAJORVERSION   1
00068 #define JSMINORVERSION   0
00069 #endif
00070 
00071 #define JSNFRAMESOFFSET  (strlen(JSHEADERSTRING) + 20)
00072 
00073 #define JSNOERR             0
00074 #define JSBADFILE           1
00075 #define JSBADFORMAT         2
00076 
00077 
00078 #define JSOPT_NOOPTIONS     0x0000
00079 #define JSOPT_STRUCTURE     0x0001
00080 #define JSOPT_BONDS         0x0002
00081 #define JSOPT_BONDORDERS    0x0004
00082 #define JSOPT_OCCUPANCY     0x0008
00083 #define JSOPT_BFACTOR       0x0010
00084 #define JSOPT_MASS          0x0020
00085 #define JSOPT_CHARGE        0x0040
00086 #define JSOPT_RADIUS        0x0080
00087 #define JSOPT_ATOMICNUMBER  0x0100
00088 
00089 typedef struct {
00090   fio_fd fd;
00091   int natoms;
00092 
00093 #if JSMAJORVERSION > 1
00094   /* structure info */
00095   int optflags;
00096   molfile_atom_t *atomlist;
00097   molfile_metadata_t *meta;
00098   int nbonds;
00099   int *bondfrom;
00100   int *bondto;
00101   float *bondorders;
00102 #endif
00103 
00104   /* trajectory info */
00105   int nframes;
00106   double tsdelta;
00107   int reverseendian;
00108   int with_unitcell;
00109 
00110 } jshandle;
00111 
00112 static void *open_js_read(const char *path, const char *filetype, int *natoms) {
00113   jshandle *js;
00114   int jsmagicnumber, jsendianism, jsmajorversion, jsminorversion;
00115   struct stat stbuf;
00116   char strbuf[1024];
00117   int rc = 0;
00118 
00119   if (!path) return NULL;
00120 
00121   /* See if the file exists, and get its size */
00122   memset(&stbuf, 0, sizeof(struct stat));
00123   if (stat(path, &stbuf)) {
00124     printf("jsplugin) Could not access file '%s'.\n", path);
00125     return NULL;
00126   }
00127 
00128   js = (jshandle *)malloc(sizeof(jshandle));
00129   memset(js, 0, sizeof(jshandle));
00130   if (fio_open(path, FIO_READ, &js->fd) < 0) {
00131     printf("jsplugin) Could not open file '%s' for reading.\n", path);
00132     free(js);
00133     return NULL;
00134   }
00135 
00136   /* emit header information */
00137   fio_fread(strbuf, strlen(JSHEADERSTRING), 1, js->fd);
00138   strbuf[strlen(JSHEADERSTRING)] = '\0';
00139   if (strcmp(strbuf, JSHEADERSTRING)) {
00140     printf("jsplugin) Bad trajectory header!\n");
00141     printf("jsplugin) Read string: %s\n", strbuf);
00142     return NULL;
00143   }
00144 
00145   fio_read_int32(js->fd, &jsmagicnumber);
00146   fio_read_int32(js->fd, &jsendianism);
00147   fio_read_int32(js->fd, &jsmajorversion);
00148   fio_read_int32(js->fd, &jsminorversion);
00149   fio_read_int32(js->fd, &js->natoms);
00150   fio_read_int32(js->fd, &js->nframes);
00151   if ((jsmagicnumber != JSMAGICNUMBER) || (jsendianism != JSENDIANISM)) {
00152     printf("jsplugin) opposite endianism trajectory file, enabling byte swapping\n");
00153     js->reverseendian = 1;
00154     swap4_aligned(&jsmagicnumber, 1);
00155     swap4_aligned(&jsendianism, 1);
00156     swap4_aligned(&jsmajorversion, 1);
00157     swap4_aligned(&jsminorversion, 1);
00158     swap4_aligned(&js->natoms, 1);
00159     swap4_aligned(&js->nframes, 1);
00160   }
00161 
00162   if ((jsmagicnumber != JSMAGICNUMBER) || (jsendianism != JSENDIANISM)) {
00163     printf("jsplugin) read_jsreader returned %d\n", rc);
00164     fio_fclose(js->fd);
00165     free(js);
00166     return NULL;
00167   }
00168   
00169   *natoms = js->natoms;
00170   return js;
00171 }
00172 
00173 
00174 #if JSMAJORVERSION > 1
00175 
00176 static int read_js_structure(void *mydata, int *optflags,
00177                              molfile_atom_t *atoms) {
00178   jshandle *js = (jshandle *) mydata;
00179   int i;
00180 
00181   *optflags = MOLFILE_NOOPTIONS; /* set to no options until we read them */
00182 
00183   /* write flags data to the file */
00184   fio_read_int32(js->fd, &js->optflags); 
00185   if (js->reverseendian)
00186     swap4_aligned(&js->optflags, 1);
00187 printf("jsplugin) read option flags: %0x08x\n", js->optflags);
00188 
00189   /* determine whether or not this file contains structure info or not */
00190   if (js->optflags & JSOPT_STRUCTURE) {
00191     int numatomnames, numatomtypes, numresnames, numsegids, numchains;
00192     char **atomnames = NULL;
00193     char **atomtypes = NULL;
00194     char **resnames = NULL;
00195     char **segids = NULL;
00196     char **chains = NULL;
00197     short *shortbuf = NULL; /* temp buf for decoding atom records */
00198     int *intbuf = NULL;     /* temp buf for decoding atom records */
00199     float *fltbuf = NULL;   /* temp buf for decoding atom records */
00200  
00201     /* read in block of name string table sizes */
00202     fio_read_int32(js->fd, &numatomnames); 
00203     fio_read_int32(js->fd, &numatomtypes); 
00204     fio_read_int32(js->fd, &numresnames);
00205     fio_read_int32(js->fd, &numsegids);
00206     fio_read_int32(js->fd, &numchains); 
00207     if (js->reverseendian) {
00208       swap4_aligned(&numatomnames, js->natoms);
00209       swap4_aligned(&numatomtypes, js->natoms);
00210       swap4_aligned(&numresnames, js->natoms);
00211       swap4_aligned(&numsegids, js->natoms);
00212       swap4_aligned(&numchains, js->natoms);
00213     }
00214 
00215 printf("jsplugin) reading string tables...\n");
00216 printf("jsplugin) %d %d %d %d %d\n",
00217        numatomnames, numatomtypes, numresnames, numsegids, numchains);
00218 
00219     /* allocate string tables */
00220     atomnames = (char **) malloc(numatomnames * sizeof(char *));
00221     atomtypes = (char **) malloc(numatomtypes * sizeof(char *));
00222     resnames  = (char **) malloc(numresnames  * sizeof(char *));
00223     segids    = (char **) malloc(numsegids    * sizeof(char *));
00224     chains    = (char **) malloc(numchains    * sizeof(char *));
00225 
00226 printf("jsplugin)   atom names...\n");
00227     /* read in the string tables */
00228     for (i=0; i<numatomnames; i++) {
00229       atomnames[i] = (char *) malloc(16 * sizeof(char));
00230       fio_fread(atomnames[i], 16 * sizeof(char), 1, js->fd);
00231     }
00232 
00233 printf("jsplugin)   atom types...\n");
00234     for (i=0; i<numatomtypes; i++) {
00235       atomtypes[i] = (char *) malloc(16 * sizeof(char));
00236       fio_fread(atomtypes[i], 16 * sizeof(char), 1, js->fd);
00237     }
00238 
00239 printf("jsplugin)   residue names...\n");
00240     for (i=0; i<numresnames; i++) {
00241       resnames[i] = (char *) malloc(8 * sizeof(char));
00242       fio_fread(resnames[i], 8 * sizeof(char), 1, js->fd);
00243     }
00244 
00245 printf("jsplugin)   segment names...\n");
00246     for (i=0; i<numsegids; i++) {
00247       segids[i] = (char *) malloc(8 * sizeof(char));
00248       fio_fread(segids[i], 8 * sizeof(char), 1, js->fd);
00249     }
00250 
00251 printf("jsplugin)   chain names...\n");
00252     for (i=0; i<numchains; i++) {
00253       chains[i] = (char *) malloc(2 * sizeof(char));
00254       fio_fread(chains[i], 2 * sizeof(char), 1, js->fd);
00255     }
00256 
00257 printf("jsplugin) reading numeric field tables...\n");
00258     /* read in all of the atom fields */
00259     shortbuf = (void *) malloc(js->natoms * sizeof(short));
00260 
00261 printf("jsplugin)   atom name indices...\n");
00262     /* read in atom names */
00263     fio_fread(shortbuf, js->natoms * sizeof(short), 1, js->fd);
00264     if (js->reverseendian)
00265       swap2_aligned(shortbuf, js->natoms);
00266     for (i=0; i<js->natoms; i++) {
00267       strcpy(atoms[i].name, atomnames[shortbuf[i]]);
00268     }    
00269 
00270 printf("jsplugin)   atom type indices...\n");
00271     /* read in atom types */
00272     fio_fread(shortbuf, js->natoms * sizeof(short), 1, js->fd);
00273     if (js->reverseendian)
00274       swap2_aligned(shortbuf, js->natoms);
00275     for (i=0; i<js->natoms; i++) {
00276       strcpy(atoms[i].type, atomtypes[shortbuf[i]]);
00277     }    
00278 
00279 printf("jsplugin)   residue name indices...\n");
00280     /* read in resnames */
00281     fio_fread(shortbuf, js->natoms * sizeof(short), 1, js->fd);
00282     if (js->reverseendian)
00283       swap2_aligned(shortbuf, js->natoms);
00284     for (i=0; i<js->natoms; i++) {
00285       strcpy(atoms[i].resname, resnames[shortbuf[i]]);
00286     }    
00287     
00288 printf("jsplugin)   segment name indices...\n");
00289     /* read in segids */
00290     fio_fread(shortbuf, js->natoms * sizeof(short), 1, js->fd);
00291     if (js->reverseendian)
00292       swap2_aligned(shortbuf, js->natoms);
00293     for (i=0; i<js->natoms; i++) {
00294       strcpy(atoms[i].segid, segids[shortbuf[i]]);
00295     }    
00296 
00297 printf("jsplugin)   chain name indices...\n");
00298     /* read in chains */
00299     fio_fread(shortbuf, js->natoms * sizeof(short), 1, js->fd);
00300     if (js->reverseendian)
00301       swap2_aligned(shortbuf, js->natoms);
00302     for (i=0; i<js->natoms; i++) {
00303       strcpy(atoms[i].chain, chains[shortbuf[i]]);
00304     }    
00305 
00306     if (shortbuf != NULL) {
00307       free(shortbuf);
00308       shortbuf=NULL;
00309     }
00310 
00311     /* 
00312      * read in integer data blocks 
00313      */
00314     intbuf = (int *) malloc(js->natoms * sizeof(int));
00315 
00316 printf("jsplugin)   residue indices...\n");
00317     /* read in resid */
00318     fio_fread(intbuf, js->natoms * sizeof(int), 1, js->fd);
00319     if (js->reverseendian)
00320       swap4_aligned(intbuf, js->natoms);
00321     for (i=0; i<js->natoms; i++) {
00322       atoms[i].resid = intbuf[i];
00323     }    
00324      
00325     if (intbuf != NULL) {
00326       free(intbuf);
00327       intbuf = NULL;
00328     }
00329 
00330 
00331 printf("jsplugin) reading optional per-atom tables...\n");
00332     /*
00333      * read in optional single-precision float data blocks
00334      */ 
00335     if (js->optflags & (JSOPT_OCCUPANCY | JSOPT_BFACTOR | 
00336         JSOPT_MASS | JSOPT_RADIUS | JSOPT_CHARGE)) 
00337       fltbuf = (void *) malloc(js->natoms * sizeof(float));
00338 
00339     /* read in optional data if it exists */
00340     if (js->optflags & JSOPT_OCCUPANCY) {
00341 printf("jsplugin)   occupancy...\n");
00342       *optflags |= MOLFILE_OCCUPANCY;
00343       fio_fread(fltbuf, js->natoms * sizeof(float), 1, js->fd);
00344       if (js->reverseendian)
00345         swap4_aligned(fltbuf, js->natoms);
00346       for (i=0; i<js->natoms; i++) {
00347         atoms[i].occupancy = fltbuf[i];
00348       }    
00349     }
00350 
00351     if (js->optflags & JSOPT_BFACTOR) {
00352 printf("jsplugin)   bfactor...\n");
00353       *optflags |= MOLFILE_BFACTOR;
00354       fio_fread(fltbuf, js->natoms * sizeof(float), 1, js->fd);
00355       if (js->reverseendian)
00356         swap4_aligned(fltbuf, js->natoms);
00357       for (i=0; i<js->natoms; i++) {
00358         atoms[i].bfactor = fltbuf[i];
00359       }    
00360     }
00361 
00362     if (js->optflags & JSOPT_MASS) { 
00363 printf("jsplugin)   mass...\n");
00364       *optflags |= MOLFILE_MASS;
00365       fio_fread(fltbuf, js->natoms * sizeof(float), 1, js->fd);
00366       if (js->reverseendian)
00367         swap4_aligned(fltbuf, js->natoms);
00368       for (i=0; i<js->natoms; i++) {
00369         atoms[i].mass = fltbuf[i];
00370       }    
00371     }
00372 
00373     if (js->optflags & JSOPT_CHARGE) { 
00374 printf("jsplugin)   charge...\n");
00375       *optflags |= MOLFILE_CHARGE;
00376       fio_fread(fltbuf, js->natoms * sizeof(float), 1, js->fd);
00377       if (js->reverseendian)
00378         swap4_aligned(fltbuf, js->natoms);
00379       for (i=0; i<js->natoms; i++) {
00380         atoms[i].charge = fltbuf[i];
00381       }    
00382     }
00383 
00384     if (js->optflags & JSOPT_RADIUS) { 
00385 printf("jsplugin)   radius...\n");
00386       *optflags |= MOLFILE_RADIUS;
00387       fio_fread(fltbuf, js->natoms * sizeof(float), 1, js->fd);
00388       if (js->reverseendian)
00389         swap4_aligned(fltbuf, js->natoms);
00390       for (i=0; i<js->natoms; i++) {
00391         atoms[i].radius = fltbuf[i];
00392       }    
00393     }
00394 
00395     if (fltbuf != NULL) {
00396       free(fltbuf);
00397       fltbuf=NULL;
00398     }
00399 
00400     /*
00401      * read in optional integer data blocks
00402      */ 
00403     if (js->optflags & JSOPT_ATOMICNUMBER)
00404       intbuf = (void *) malloc(js->natoms * sizeof(int));
00405 
00406     if (js->optflags & JSOPT_ATOMICNUMBER) { 
00407 printf("jsplugin)   atomic number...\n");
00408       *optflags |= MOLFILE_ATOMICNUMBER;
00409       fio_fread(intbuf, js->natoms * sizeof(int), 1, js->fd);
00410       if (js->reverseendian)
00411         swap4_aligned(intbuf, js->natoms);
00412       for (i=0; i<js->natoms; i++) {
00413         atoms[i].atomicnumber = intbuf[i];
00414       }    
00415     }
00416 
00417     if (intbuf != NULL) {
00418       free(intbuf);
00419       intbuf = NULL;
00420     }
00421 
00422 
00423     /*
00424      * read in bonds and fractional bond orders
00425      */ 
00426     if (js->optflags & JSOPT_BONDS) {
00427       fio_fread(&js->nbonds, sizeof(int), 1, js->fd);
00428       if (js->reverseendian)
00429         swap4_aligned(&js->nbonds, 1);
00430 printf("jsplugin)   %d bonds...\n", js->nbonds);
00431 
00432       js->bondfrom = (void *) malloc(js->nbonds * sizeof(int));
00433       js->bondto = (void *) malloc(js->nbonds * sizeof(int));
00434       fio_fread(js->bondfrom, js->nbonds * sizeof(int), 1, js->fd);
00435       fio_fread(js->bondto, js->nbonds * sizeof(int), 1, js->fd);
00436       if (js->reverseendian) {
00437         swap4_aligned(js->bondfrom, js->nbonds);
00438         swap4_aligned(js->bondto, js->nbonds);
00439       }
00440 
00441       if (js->optflags & JSOPT_BONDORDERS) {
00442 printf("jsplugin)   bond orders...\n");
00443         js->bondorders = (void *) malloc(js->nbonds * sizeof(float));
00444         fio_fread(js->bondorders, js->nbonds * sizeof(float), 1, js->fd);
00445         if (js->reverseendian)
00446           swap4_aligned(js->bondorders, js->nbonds);
00447       }
00448     }
00449 
00450 printf("jsplugin) final optflags: %08x\n", *optflags);
00451 printf("jsplugin) structure information complete\n");
00452 
00453     return MOLFILE_SUCCESS;
00454   }
00455 
00456 printf("jsplugin) no structure information available\n");
00457 
00458   /* else, we have no structure information */
00459   return MOLFILE_NOSTRUCTUREDATA;
00460 }
00461 
00462 static int read_js_bonds(void *v, int *nbonds, int **fromptr, int **toptr, float **bondorder) {
00463   jshandle *js = (jshandle *)v;
00464 
00465   *nbonds = 0;
00466   *fromptr = NULL;
00467   *toptr = NULL;
00468   *bondorder = NULL;
00469 
00470   if (js->optflags & JSOPT_BONDS) {
00471     /* save bond info until we actually write out the structure file */
00472     *nbonds = js->nbonds;
00473     *fromptr = js->bondfrom;
00474     *toptr = js->bondto;
00475 
00476     if (js->optflags & JSOPT_BONDORDERS) {
00477       *bondorder = js->bondorders;
00478     }
00479   }
00480 
00481   return MOLFILE_SUCCESS;
00482 }
00483 
00484 #endif
00485 
00486 
00487 
00488 
00489 
00490 
00491 static int read_js_timestep(void *v, int natoms, molfile_timestep_t *ts) {
00492   jshandle *js = (jshandle *)v;
00493   int framelen = (natoms * 3 * sizeof(float)) + (6 * sizeof(double));;
00494 
00495   /* if we have a valid ts pointer, read the timestep, otherwise skip it */ 
00496   if (ts != NULL) {
00497     int readlen; 
00498     fio_iovec iov[2];
00499     double unitcell[6];
00500     unitcell[0] = unitcell[2] = unitcell[5] = 1.0f;
00501     unitcell[1] = unitcell[3] = unitcell[4] = 90.0f;
00502   
00503     /* setup the I/O vector */
00504     iov[0].iov_base = (fio_caddr_t) ts->coords;   /* read coordinates    */
00505     iov[0].iov_len  = natoms * 3 * sizeof(float);
00506     iov[1].iov_base = (fio_caddr_t) &unitcell[0]; /* read PBC unit cell  */
00507     iov[1].iov_len  = 6 * sizeof(double);
00508 
00509     /* Do all of the reads with a single syscall, for peak efficiency. */
00510     /* On smart kernels, readv() causes only one context switch, and   */
00511     /* can effeciently scatter the reads to the various buffers.       */
00512     readlen = fio_readv(js->fd, &iov[0], 2); 
00513   
00514     /* check the number of read bytes versus what we expected */
00515     if (readlen != framelen)
00516       return MOLFILE_EOF;
00517 
00518     /* perform byte swapping if necessary */
00519     if (js->reverseendian) {
00520       swap4_aligned(ts->coords, natoms * 3);
00521       swap8_aligned(unitcell, 6);
00522     }
00523 
00524     /* copy unit cell values into VMD */
00525     ts->A = unitcell[0];
00526     ts->B = unitcell[1];
00527     ts->C = unitcell[2];
00528     ts->alpha = 90.0 - asin(unitcell[3]) * 90.0 / M_PI_2;
00529     ts->beta  = 90.0 - asin(unitcell[4]) * 90.0 / M_PI_2;
00530     ts->gamma = 90.0 - asin(unitcell[5]) * 90.0 / M_PI_2;
00531   } else {
00532     /* skip this frame, seek to the next frame */
00533     if (fio_fseek(js->fd, framelen, FIO_SEEK_CUR)) 
00534       return MOLFILE_EOF;
00535   }
00536  
00537   return MOLFILE_SUCCESS;
00538 }
00539  
00540 
00541 static void close_js_read(void *v) {
00542   jshandle *js = (jshandle *)v;
00543   fio_fclose(js->fd);
00544 
00545 #if JSMAJORVERSION > 1
00546   if (js->bondfrom)
00547     free(js->bondfrom);
00548   if (js->bondto)
00549     free(js->bondto);
00550   if (js->bondorders)
00551     free(js->bondorders);
00552 #endif
00553 
00554   free(js);
00555 }
00556 
00557 
00558 static void *open_js_write(const char *path, const char *filetype, int natoms) {
00559   jshandle *js;
00560 
00561   js = (jshandle *)malloc(sizeof(jshandle));
00562   memset(js, 0, sizeof(jshandle));
00563   if (fio_open(path, FIO_WRITE, &js->fd) < 0) {
00564     printf("jsplugin) Could not open file %s for writing\n", path);
00565     free(js);
00566     return NULL;
00567   }
00568 
00569   js->natoms = natoms;
00570   js->with_unitcell = 1;
00571 
00572   /* emit header information */
00573   fio_write_str(js->fd, JSHEADERSTRING);
00574   fio_write_int32(js->fd, JSMAGICNUMBER);
00575   fio_write_int32(js->fd, JSENDIANISM);
00576   fio_write_int32(js->fd, JSMAJORVERSION);
00577   fio_write_int32(js->fd, JSMINORVERSION);
00578 
00579   /* write number of atoms */
00580   fio_write_int32(js->fd, natoms);
00581 
00582   /* write number of frames, to be updated later */
00583   js->nframes = 0;
00584   fio_write_int32(js->fd, js->nframes);
00585 
00586   return js;
00587 }
00588 
00589 
00590 #if JSMAJORVERSION > 1
00591 
00592 static int write_js_structure(void *mydata, int optflags,
00593                               const molfile_atom_t *atoms) {
00594   jshandle *js = (jshandle *) mydata;
00595   int i;
00596 
00597   js->optflags |= JSOPT_STRUCTURE;
00598 
00599   if (optflags & MOLFILE_OCCUPANCY)
00600     js->optflags |= JSOPT_OCCUPANCY;
00601 
00602   if (optflags & MOLFILE_BFACTOR)
00603     js->optflags |= JSOPT_BFACTOR;
00604 
00605   if (optflags & MOLFILE_BFACTOR)
00606     js->optflags |= JSOPT_BFACTOR;
00607 
00608   if (optflags & MOLFILE_MASS)
00609     js->optflags |= JSOPT_MASS;
00610 
00611   if (optflags & MOLFILE_CHARGE)
00612     js->optflags |= JSOPT_CHARGE;
00613  
00614   if (optflags & MOLFILE_RADIUS)
00615     js->optflags |= JSOPT_RADIUS;
00616 
00617   if (optflags & MOLFILE_ATOMICNUMBER)
00618     js->optflags |= JSOPT_ATOMICNUMBER;
00619 
00620   /* write flags data to the file */
00621   fio_write_int32(js->fd, js->optflags); 
00622 printf("jsplugin) writing option flags: %0x08x\n", js->optflags);
00623 
00624 printf("jsplugin) writing structure...\n");
00625   /* determine whether or not this file contains structure info or not */
00626   if (js->optflags & JSOPT_STRUCTURE) {
00627     int numatomnames, numatomtypes, numresnames, numsegids, numchains;
00628     char **atomnames = NULL;
00629     char **atomtypes = NULL;
00630     char **resnames = NULL;
00631     char **segids = NULL;
00632     char **chains = NULL;
00633     short *shortbuf = NULL; /* temp buf for encoding atom records */
00634     int *intbuf = NULL;     /* temp buf for encoding atom records */
00635     float *fltbuf = NULL;   /* temp buf for encoding atom records */
00636 
00637     hash_t tmphash;         /* temporary hash table */
00638     hash_t atomnamehash;
00639     hash_t atomtypehash;
00640     hash_t resnamehash;
00641     hash_t segidhash;
00642     hash_t chainhash;
00643     int hashcnt;
00644 
00645 
00646 printf("jsplugin) counting atom names, types, etc...\n");
00647     /* generate hash tables to count the number of unique strings */
00648     hash_init(&tmphash, 127);
00649     for (i=0; i<js->natoms; i++)
00650       hash_insert(&tmphash, atoms[i].name, 0);
00651     numatomnames = tmphash.entries; /* XXX need a query API for this... */
00652     hash_destroy(&tmphash);
00653 
00654     hash_init(&tmphash, 127);
00655     for (i=0; i<js->natoms; i++)
00656       hash_insert(&tmphash, atoms[i].type, 0);
00657     numatomtypes = tmphash.entries; /* XXX need a query API for this... */
00658     hash_destroy(&tmphash);
00659 
00660     hash_init(&tmphash, 127);
00661     for (i=0; i<js->natoms; i++)
00662       hash_insert(&tmphash, atoms[i].resname, 0);
00663     numresnames = tmphash.entries; /* XXX need a query API for this... */
00664     hash_destroy(&tmphash);
00665 
00666     hash_init(&tmphash, 127);
00667     for (i=0; i<js->natoms; i++)
00668       hash_insert(&tmphash, atoms[i].segid, 0);
00669     numsegids = tmphash.entries; /* XXX need a query API for this... */
00670     hash_destroy(&tmphash);
00671 
00672     hash_init(&tmphash, 127);
00673     for (i=0; i<js->natoms; i++)
00674       hash_insert(&tmphash, atoms[i].chain, 0);
00675     numchains = tmphash.entries; /* XXX need a query API for this... */
00676     hash_destroy(&tmphash);
00677  
00678 printf("jsplugin) writing unique string counts...\n");
00679 printf("jsplugin) %d %d %d %d %d\n",
00680        numatomnames, numatomtypes, numresnames, numsegids, numchains);
00681 
00682     /* write block of name string table sizes */
00683     fio_write_int32(js->fd, numatomnames); 
00684     fio_write_int32(js->fd, numatomtypes); 
00685     fio_write_int32(js->fd, numresnames);
00686     fio_write_int32(js->fd, numsegids);
00687     fio_write_int32(js->fd, numchains); 
00688 
00689 printf("jsplugin) writing string tables...\n");
00690 
00691     atomnames = (char **) malloc(numatomnames * sizeof(char *));
00692     atomtypes = (char **) malloc(numatomtypes * sizeof(char *));
00693     resnames = (char **) malloc(numresnames * sizeof(char *));
00694     segids = (char **) malloc(numsegids * sizeof(char *));
00695     chains = (char **) malloc(numchains * sizeof(char *));
00696 
00697 printf("jsplugin)   atom names...\n");
00698     /* generate and write out the string tables */
00699     hash_init(&atomnamehash, 127);
00700     for (hashcnt=0,i=0; i<js->natoms; i++) {
00701       /* add a new string table entry for hash inserts that don't yet exist */
00702       if (hash_insert(&atomnamehash, atoms[i].name, hashcnt) == HASH_FAIL) {
00703         atomnames[hashcnt] = (char *) malloc(16 * sizeof(char));
00704         strcpy(atomnames[hashcnt], atoms[i].name);
00705         hashcnt++;
00706       }
00707     }
00708     for (i=0; i<numatomnames; i++) {
00709       fio_fwrite(atomnames[i], 16 * sizeof(char), 1, js->fd);
00710     }
00711 
00712 
00713 printf("jsplugin)   atom types...\n");
00714     hash_init(&atomtypehash, 127);
00715     for (hashcnt=0,i=0; i<js->natoms; i++) {
00716       /* add a new string table entry for hash inserts that don't yet exist */
00717       if (hash_insert(&atomtypehash, atoms[i].type, hashcnt) == HASH_FAIL) {
00718         atomtypes[hashcnt] = (char *) malloc(16 * sizeof(char));
00719         strcpy(atomtypes[hashcnt], atoms[i].type);
00720         hashcnt++;
00721       }
00722     }
00723     for (i=0; i<numatomtypes; i++) {
00724       fio_fwrite(atomtypes[i], 16 * sizeof(char), 1, js->fd);
00725     }
00726 
00727 
00728 printf("jsplugin)   residue names...\n");
00729     hash_init(&resnamehash, 127);
00730     for (hashcnt=0,i=0; i<js->natoms; i++) {
00731       /* add a new string table entry for hash inserts that don't yet exist */
00732       if (hash_insert(&resnamehash, atoms[i].resname, hashcnt) == HASH_FAIL) {
00733         resnames[hashcnt] = (char *) malloc(8 * sizeof(char));
00734         strcpy(resnames[hashcnt], atoms[i].resname);
00735         hashcnt++;
00736       }
00737     }
00738     for (i=0; i<numresnames; i++) {
00739       fio_fwrite(resnames[i], 8 * sizeof(char), 1, js->fd);
00740     }
00741 
00742 
00743 printf("jsplugin)   segment names...\n");
00744     hash_init(&segidhash, 127);
00745     for (hashcnt=0,i=0; i<js->natoms; i++) {
00746       /* add a new string table entry for hash inserts that don't yet exist */
00747       if (hash_insert(&segidhash, atoms[i].segid, hashcnt) == HASH_FAIL) {
00748         segids[hashcnt] = (char *) malloc(8 * sizeof(char));
00749         strcpy(segids[hashcnt], atoms[i].segid);
00750         hashcnt++;
00751       }
00752     }
00753     for (i=0; i<numsegids; i++) {
00754       fio_fwrite(segids[i], 8 * sizeof(char), 1, js->fd);
00755     }
00756 
00757 
00758 printf("jsplugin)   chain names...\n");
00759     hash_init(&chainhash, 127);
00760     for (hashcnt=0,i=0; i<js->natoms; i++) {
00761       /* add a new string table entry for hash inserts that don't yet exist */
00762       if (hash_insert(&chainhash, atoms[i].chain, hashcnt) == HASH_FAIL) {
00763         chains[hashcnt] = (char *) malloc(2 * sizeof(char));
00764         strcpy(chains[hashcnt], atoms[i].chain);
00765         hashcnt++;
00766       }
00767     }
00768     for (i=0; i<numchains; i++) {
00769       fio_fwrite(chains[i], 2 * sizeof(char), 1, js->fd);
00770     }
00771 
00772 
00773 printf("jsplugin) writing numeric field tables...\n");
00774     /* write out all of the atom fields */
00775     shortbuf = (void *) malloc(js->natoms * sizeof(short));
00776 
00777     /* write out atom names */
00778     for (i=0; i<js->natoms; i++) {
00779       shortbuf[i] = hash_lookup(&atomnamehash, atoms[i].name);
00780     }    
00781     fio_fwrite(shortbuf, js->natoms * sizeof(short), 1, js->fd);
00782 
00783     /* write out atom types */
00784     for (i=0; i<js->natoms; i++) {
00785       shortbuf[i] = hash_lookup(&atomtypehash, atoms[i].type);
00786     }    
00787     fio_fwrite(shortbuf, js->natoms * sizeof(short), 1, js->fd);
00788 
00789     /* write out resnames */
00790     for (i=0; i<js->natoms; i++) {
00791       shortbuf[i] = hash_lookup(&resnamehash, atoms[i].resname);
00792     }    
00793     fio_fwrite(shortbuf, js->natoms * sizeof(short), 1, js->fd);
00794     
00795     /* write out segids */
00796     for (i=0; i<js->natoms; i++) {
00797       shortbuf[i] = hash_lookup(&segidhash, atoms[i].segid);
00798     }    
00799     fio_fwrite(shortbuf, js->natoms * sizeof(short), 1, js->fd);
00800 
00801     /* write out chains */
00802     for (i=0; i<js->natoms; i++) {
00803       shortbuf[i] = hash_lookup(&chainhash, atoms[i].chain);
00804     }    
00805     fio_fwrite(shortbuf, js->natoms * sizeof(short), 1, js->fd);
00806 
00807     if (shortbuf != NULL) {
00808       free(shortbuf);
00809       shortbuf=NULL;
00810     }
00811 
00812     /* done with hash tables */
00813     hash_destroy(&atomnamehash);
00814     hash_destroy(&atomtypehash);
00815     hash_destroy(&resnamehash);
00816     hash_destroy(&segidhash);
00817     hash_destroy(&chainhash);
00818 
00819 
00820     /* 
00821      * write out integer data blocks 
00822      */
00823     intbuf = (int *) malloc(js->natoms * sizeof(int));
00824 
00825 printf("jsplugin)   residue indices...\n");
00826     /* write out resid */
00827     for (i=0; i<js->natoms; i++) {
00828       intbuf[i] = atoms[i].resid;
00829     }    
00830     fio_fwrite(intbuf, js->natoms * sizeof(int), 1, js->fd);
00831      
00832     if (intbuf != NULL) {
00833       free(intbuf);
00834       intbuf = NULL;
00835     }
00836 
00837 printf("jsplugin) writing optional per-atom tables...\n");
00838     /*
00839      * write out optional single-precision float data blocks
00840      */ 
00841     if (js->optflags & (JSOPT_OCCUPANCY | JSOPT_BFACTOR | 
00842         JSOPT_MASS | JSOPT_RADIUS | JSOPT_CHARGE)) 
00843       fltbuf = (void *) malloc(js->natoms * sizeof(float));
00844 
00845     /* write out optional data if it exists */
00846 
00847     if (js->optflags & JSOPT_OCCUPANCY) {
00848 printf("jsplugin)   writing occupancy...\n");
00849       for (i=0; i<js->natoms; i++) {
00850         fltbuf[i] = atoms[i].occupancy;
00851       }    
00852       fio_fwrite(fltbuf, js->natoms * sizeof(float), 1, js->fd);
00853     }
00854 
00855     if (js->optflags & JSOPT_BFACTOR) {
00856 printf("jsplugin)   writing bfactor...\n");
00857       for (i=0; i<js->natoms; i++) {
00858         fltbuf[i] = atoms[i].bfactor;
00859       }    
00860       fio_fwrite(fltbuf, js->natoms * sizeof(float), 1, js->fd);
00861     }
00862 
00863     if (js->optflags & JSOPT_MASS) { 
00864 printf("jsplugin)   writing mass...\n");
00865       for (i=0; i<js->natoms; i++) {
00866         fltbuf[i] = atoms[i].mass;
00867       }    
00868       fio_fwrite(fltbuf, js->natoms * sizeof(float), 1, js->fd);
00869     }
00870 
00871     if (js->optflags & JSOPT_CHARGE) { 
00872 printf("jsplugin)   writing charge...\n");
00873       for (i=0; i<js->natoms; i++) {
00874         fltbuf[i] = atoms[i].charge;
00875       }    
00876       fio_fwrite(fltbuf, js->natoms * sizeof(float), 1, js->fd);
00877     }
00878 
00879     if (js->optflags & JSOPT_RADIUS) { 
00880 printf("jsplugin)   writing radius...\n");
00881       for (i=0; i<js->natoms; i++) {
00882         fltbuf[i] = atoms[i].radius;
00883       }    
00884       fio_fwrite(fltbuf, js->natoms * sizeof(float), 1, js->fd);
00885     }
00886 
00887     if (fltbuf != NULL) {
00888       free(fltbuf);
00889       fltbuf=NULL;
00890     }
00891 
00892 
00893     /*
00894      * write out optional integer data blocks
00895      */ 
00896     if (js->optflags & JSOPT_ATOMICNUMBER)
00897       intbuf = (void *) malloc(js->natoms * sizeof(int));
00898 
00899     if (js->optflags & JSOPT_ATOMICNUMBER) { 
00900 printf("jsplugin)   writing atomic number...\n");
00901       for (i=0; i<js->natoms; i++) {
00902         intbuf[i] = atoms[i].atomicnumber;
00903       }    
00904       fio_fwrite(intbuf, js->natoms * sizeof(int), 1, js->fd);
00905     }
00906 
00907     if (intbuf != NULL) {
00908       free(intbuf);
00909       intbuf = NULL;
00910     }
00911 
00912 
00913     /*
00914      * write out bonds and fractional bond orders
00915      */ 
00916     if (js->optflags & JSOPT_BONDS) {
00917 printf("jsplugin) writing bonds...\n");
00918       fio_fwrite(&js->nbonds, sizeof(int), 1, js->fd);
00919       fio_fwrite(js->bondfrom, js->nbonds * sizeof(int), 1, js->fd);
00920       fio_fwrite(js->bondto, js->nbonds * sizeof(int), 1, js->fd);
00921 
00922       if (js->optflags & JSOPT_BONDORDERS) {
00923 printf("jsplugin) writing bond orders...\n");
00924         fio_fwrite(js->bondorders, js->nbonds * sizeof(float), 1, js->fd);
00925       }
00926     }
00927 
00928     return MOLFILE_SUCCESS;
00929   }
00930 
00931   /* else, we have no structure information */
00932   return MOLFILE_NOSTRUCTUREDATA;
00933 }
00934 
00935 
00936 static int write_js_bonds(void *mydata, int nbonds, int *fromptr, int *toptr, float *bondorder) {
00937   jshandle *js = (jshandle *) mydata;
00938 
00939   if (nbonds > 0 && fromptr != NULL && toptr != NULL) {
00940     js->optflags |= JSOPT_BONDS; 
00941 
00942     /* save bond info until we actually write out the structure file */
00943     js->nbonds = nbonds;
00944     js->bondfrom = (int *) malloc(nbonds * sizeof(int));
00945     memcpy(js->bondfrom, fromptr, nbonds * sizeof(int));
00946     js->bondto = (int *) malloc(nbonds * sizeof(int));
00947     memcpy(js->bondto, toptr, nbonds * sizeof(int));
00948 
00949     if (bondorder != NULL) {
00950       js->optflags |= JSOPT_BONDORDERS;
00951       js->bondorders = (float *) malloc(nbonds * sizeof(float));
00952       memcpy(js->bondorders, bondorder, nbonds * sizeof(float));
00953     }
00954   }
00955 
00956   return MOLFILE_SUCCESS;
00957 }
00958 
00959 #endif
00960 
00961 static int write_js_timestep(void *v, const molfile_timestep_t *ts) { 
00962   jshandle *js = (jshandle *)v;
00963   double unitcell[6];
00964 
00965   js->nframes++; /* increment frame count written to the file so far */
00966 
00967   unitcell[0] = ts->A;
00968   unitcell[1] = ts->B;
00969   unitcell[2] = ts->C;
00970   unitcell[3] = sin((M_PI_2 / 90.0) * (90.0 - ts->alpha));
00971   unitcell[4] = sin((M_PI_2 / 90.0) * (90.0 - ts->beta));
00972   unitcell[5] = sin((M_PI_2 / 90.0) * (90.0 - ts->gamma));
00973 
00974   /* coordinates for all atoms */
00975   fio_fwrite(ts->coords, js->natoms * 3 * sizeof(float), 1, js->fd);
00976 
00977   /* PBC unit cell info */ 
00978   fio_fwrite(&unitcell[0], 6 * sizeof(double), 1, js->fd);
00979 
00980   return MOLFILE_SUCCESS;
00981 }
00982 
00983 static void close_js_write(void *v) {
00984   jshandle *js = (jshandle *)v;
00985 
00986   /* update the trajectory header information */
00987   fio_fseek(js->fd, JSNFRAMESOFFSET, FIO_SEEK_SET);
00988   fio_write_int32(js->fd, js->nframes);
00989   fio_fseek(js->fd, 0, FIO_SEEK_END);
00990 
00991   fio_fclose(js->fd);
00992 
00993 #if JSMAJORVERSION > 1
00994   if (js->bondfrom)
00995     free(js->bondfrom);
00996   if (js->bondto)
00997     free(js->bondto);
00998   if (js->bondorders)
00999     free(js->bondorders);
01000 #endif
01001 
01002   free(js);
01003 }
01004 
01005 
01006 /*
01007  * Initialization stuff here
01008  */
01009 static molfile_plugin_t plugin;
01010 
01011 VMDPLUGIN_API int VMDPLUGIN_init() {
01012   memset(&plugin, 0, sizeof(molfile_plugin_t));
01013   plugin.abiversion = vmdplugin_ABIVERSION;
01014   plugin.type = MOLFILE_PLUGIN_TYPE;
01015   plugin.name = "js";
01016   plugin.prettyname = "js";
01017   plugin.author = "John Stone";
01018   plugin.majorv = 0;
01019   plugin.minorv = 9;
01020   plugin.is_reentrant = VMDPLUGIN_THREADSAFE;
01021   plugin.filename_extension = "js";
01022   plugin.open_file_read = open_js_read;
01023 #if JSMAJORVERSION > 1
01024   plugin.read_structure = read_js_structure;
01025   plugin.read_bonds = read_js_bonds;
01026 #endif
01027   plugin.read_next_timestep = read_js_timestep;
01028   plugin.close_file_read = close_js_read;
01029   plugin.open_file_write = open_js_write;
01030 #if JSMAJORVERSION > 1
01031   plugin.write_structure = write_js_structure;
01032   plugin.write_bonds = write_js_bonds;
01033 #endif
01034   plugin.write_timestep = write_js_timestep;
01035   plugin.close_file_write = close_js_write;
01036   return VMDPLUGIN_SUCCESS;
01037 }
01038 
01039 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
01040   (*cb)(v, (vmdplugin_t *)&plugin);
01041   return VMDPLUGIN_SUCCESS;
01042 }
01043 
01044 VMDPLUGIN_API int VMDPLUGIN_fini() {
01045   return VMDPLUGIN_SUCCESS;
01046 }
01047 
01048   
01049 #ifdef TEST_JSPLUGIN
01050 
01051 #include <sys/time.h>
01052 
01053 /* get the time of day from the system clock, and store it (in seconds) */
01054 double time_of_day(void) {
01055 #if defined(_MSC_VER)
01056   double t;
01057 
01058   t = GetTickCount();
01059   t = t / 1000.0;
01060 
01061   return t;
01062 #else
01063   struct timeval tm;
01064   struct timezone tz;
01065 
01066   gettimeofday(&tm, &tz);
01067   return((double)(tm.tv_sec) + (double)(tm.tv_usec)/1000000.0);
01068 #endif
01069 }
01070 
01071 int main(int argc, char *argv[]) {
01072   molfile_timestep_t timestep;
01073   void *v;
01074   jshandle *js;
01075   int i, natoms;
01076   float sizeMB =0.0, totalMB = 0.0;
01077   double starttime, endtime, totaltime = 0.0;
01078 
01079   while (--argc) {
01080     ++argv; 
01081     natoms = 0;
01082     v = open_js_read(*argv, "js", &natoms);
01083     if (!v) {
01084       printf("jsplugin) open_js_read failed for file %s\n", *argv);
01085       return 1;
01086     }
01087     js = (jshandle *)v;
01088     sizeMB = ((natoms * 3.0) * js->nframes * 4.0) / (1024.0 * 1024.0);
01089     totalMB += sizeMB; 
01090     printf("jsplugin) file: %s\n", *argv);
01091     printf("jsplugin)   %d atoms, %d frames, size: %6.1fMB\n", natoms, js->nframes, sizeMB);
01092 
01093     starttime = time_of_day();
01094     timestep.coords = (float *)malloc(3*sizeof(float)*natoms);
01095     for (i=0; i<js->nframes; i++) {
01096       int rc = read_js_timestep(v, natoms, &timestep);
01097       if (rc) {
01098         printf("jsplugin) error in read_js_timestep on frame %d\n", i);
01099         return 1;
01100       }
01101     }
01102     endtime = time_of_day();
01103     close_js_read(v);
01104     totaltime += endtime - starttime;
01105     printf("jsplugin)  Time: %5.1f seconds\n", endtime - starttime);
01106     printf("jsplugin)  Speed: %5.1f MB/sec, %5.1f timesteps/sec\n", sizeMB / (endtime - starttime), (js->nframes / (endtime - starttime)));
01107   }
01108   printf("jsplugin) Overall Size: %6.1f MB\n", totalMB);
01109   printf("jsplugin) Overall Time: %6.1f seconds\n", totaltime);
01110   printf("jsplugin) Overall Speed: %5.1f MB/sec\n", totalMB / totaltime);
01111   return 0;
01112 }
01113       
01114 #endif
01115 

Generated on Fri Sep 5 01:38:31 2008 for VMD Plugins (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002