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

avsplugin.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: avsplugin.C,v $
00013  *      $Author: johns $       $Locker:  $             $State: Exp $
00014  *      $Revision: 1.23 $       $Date: 2016/11/28 05:01:53 $
00015  *
00016  ***************************************************************************/
00017 
00018 /*
00019  * AVS field files
00020  *
00021  * XXX - This plugin currently only supports the specific subset of AVS field
00022  * files that are produced by autodock. 'field' type must be 'uniform',
00023  * 'data' must be of type 'float', 'ndim' and 'nspace' must be 3, and
00024  * 'filetype' of all files referenced must be 'ascii'. 
00025  *
00026  * XXX - The plugin also expects the values to appear in a certain order,
00027  * this should definitely be fixed.
00028  *
00029  * More info for this format can be found at
00030  * <http://astronomy.swin.edu.au/~pbourke/geomformats/field/>
00031  *
00032  */
00033 
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <ctype.h>
00037 #include <string.h>
00038 
00039 #if defined(_AIX)
00040 #include <strings.h>
00041 #endif
00042 
00043 #if defined(WIN32) || defined(WIN64)
00044 #define strcasecmp  stricmp
00045 #define strncasecmp strnicmp
00046 #endif
00047 
00048 #include "molfile_plugin.h"
00049 
00050 #define LINESIZE 256
00051 
00052 typedef struct {
00053   char filename[256]; /* XXX - LAME */
00054   int filetype, skip, offset, stride;
00055 } datasource_t;
00056 
00057 typedef struct {
00058   int nsets;
00059   molfile_volumetric_t *vol;
00060   datasource_t *data;
00061 } avsfield_t;
00062 
00063 enum {NONE, ASCII, BINARY, UNFORMATTED};  /* File types */
00064 enum {UNIFORM, IRREGULAR, RECTILINEAR};   /* Field types */
00065 enum {AVSFLOAT};                          /* Data types */
00066 
00067 /* Reads lines from the stream into the array pointed to by s.
00068  * Returns a pointer to s when the first non-comment line is read or NULL on
00069  * error.
00070  */
00071 static char *get_string(char *s, int n, FILE *stream) {
00072   do {
00073     if (fgets(s, n, stream) == NULL) {
00074       fprintf(stderr, "avsplugin) Error reading string.\n");
00075       return NULL;
00076     }
00077   } while (s[0] == '#');
00078   return s;
00079 }
00080 
00081 /* Read information from a string and store it into a datasource structure.
00082  * Returns 0 on success, 1 on error.
00083  */
00084 static int read_datasource(char *s, datasource_t *data) {
00085   char *src, *tok, *value;
00086   src = strdup(s);
00087   tok = strtok(src, " \t\n");
00088 
00089   /* Load default values -- used if these attributes aren't set */
00090   data->skip = 0;
00091   data->offset = 0;
00092   data->stride = 1;
00093 
00094   /* Load default values -- must be changed */
00095   data->filename[0] = '\0';
00096   data->filetype = NONE;
00097 
00098   /* The first word should be "coord" or "variable" */
00099   if ( (strcasecmp(tok, "coord") != 0) && (strcasecmp(tok, "variable") != 0) ) {
00100     fprintf(stderr, "avsplugin) Improperly formatted header: expected coord or variable.\n");
00101     free(src);
00102     return 1;
00103   }
00104 
00105   /* Next should be the integer ID of the data source */
00106   tok = strtok(NULL, " \t\n");
00107   if (!isdigit(*tok)) {
00108     fprintf(stderr, "avsplugin) Improperly formatted header: expected ID.\n");
00109     free(src);
00110     return 1;
00111   }
00112 
00113   /* Now read the additional arguments */
00114   tok = strtok(NULL, " \t\n");
00115   while(tok) {
00116     value = strchr(tok, '=');
00117     if (!value) {
00118       fprintf(stderr, "avsplugin) Error reading value.\n");
00119       free(src);
00120       return 1;
00121     }
00122     value++; /* Point to the first character after '=' */
00123 
00124     if (strncasecmp(tok, "file=", value - tok) == 0) {
00125       /* XXX - This should be changed to something safer */
00126       strcpy(data->filename, value);
00127     }
00128     else if (strncasecmp(tok, "filetype=", value - tok) == 0) {
00129       /* XXX - For now, only ascii files are recognized. Other possible
00130        * values are "unformatted" for unformatted Fortran data, and "binary"
00131        * for raw binary data.
00132        */
00133       if (strcasecmp(value, "ascii") == 0) {
00134         data->filetype = ASCII;
00135       }
00136       else {
00137         fprintf(stderr, "avsplugin) Non-ASCII files are not supported.\n");
00138         free(src);
00139         return 1;
00140       }
00141     }
00142     else if (strncasecmp(tok, "skip=", value - tok) == 0) {
00143       /* XXX - This should probably be more rigorous */
00144       data->skip = atoi(value);
00145     }
00146     else if (strncasecmp(tok, "offset=", value - tok) == 0) {
00147       /* XXX - This should probably be more rigorous */
00148       data->offset = atoi(value);
00149     }
00150     else if (strncasecmp(tok, "stride=", value - tok) == 0) {
00151       /* XXX - This should definitely be more rigorous -- we don't want
00152        * stride set to 0 of the value isn't an integer. */
00153       data->stride = atoi(value);
00154     }
00155     else {
00156       /* XXX - For now, return with an error if there's an unrecognized
00157        * argument. This should probably be changed.
00158        */
00159       fprintf(stderr, "avsplugin) Unrecognized argument.\n");
00160       free(src);
00161       return 1;
00162     }
00163 
00164     tok = strtok(NULL, " \t\n");
00165   }
00166 
00167   free(src);
00168 
00169   /* Make sure the filename and filetype have been set */
00170   if ((data->filename[0] == '\0') || (data->filetype == NONE)) {
00171     fprintf(stderr, "avsplugin) Filename not set in options.\n");
00172     return 1;
00173   }
00174   
00175   return 0;
00176 }
00177 
00178 static void *open_avsfield_read(const char *filepath, const char *filetype, int *natoms) {
00179   avsfield_t *avsfield;
00180   FILE *fd;
00181   char inbuf[LINESIZE], current_file[256];
00182   int ndim, nspace, veclen, xsize, ysize, zsize, 
00183       index, i, coord_count, var_count;
00184   float value, origin[3], gridlength[3];
00185   datasource_t *coord = NULL, *variable = NULL;
00186 
00187   fd = fopen(filepath, "rb");
00188   if (!fd) {
00189     fprintf(stderr, "avsplugin) Error opening file.\n");
00190     return NULL;
00191   }
00192 
00193   /* Check for an AVS file */
00194   if (fgets(inbuf, LINESIZE, fd) == NULL) {
00195     fclose(fd);
00196     fprintf(stderr, "avsplugin) Error reading line.\n");
00197     return NULL;
00198   }
00199   if (strncmp(inbuf, "# AVS", 5) != 0) {
00200     fclose(fd);
00201     fprintf(stderr, "avsplugin) Improperly formatted header.\n");
00202     return NULL;
00203   }
00204 
00205   /* Check the number of dimensions */
00206   if (get_string(inbuf, LINESIZE, fd) == NULL) {
00207     fclose(fd);
00208     return NULL;
00209   }
00210   if (sscanf(inbuf, "ndim=%d", &ndim) != 1) {
00211     fprintf(stderr, "avsplugin) Error reading ndim.\n");
00212     fclose(fd);
00213     return NULL;
00214   }
00215   if (ndim != 3) {
00216     fprintf(stderr, "avsplugin) Error: ndim must be 3.\n");
00217     fclose(fd);
00218     return NULL;
00219   }
00220 
00221   /* Find the size of the grid in grid units */
00222   if (get_string(inbuf, LINESIZE, fd) == NULL) {
00223     fclose(fd);
00224     return NULL;
00225   }
00226   if (sscanf(inbuf, "dim1=%d", &xsize) != 1) {
00227     fprintf(stderr, "avsplugin) Error reading dim1.\n");
00228     fclose(fd);
00229     return NULL;
00230   }
00231   if (get_string(inbuf, LINESIZE, fd) == NULL) {
00232     fclose(fd);
00233     return NULL;
00234   }
00235   if (sscanf(inbuf, "dim2=%d", &ysize) != 1) {
00236     fprintf(stderr, "avsplugin) Error reading dim2.\n");
00237     fclose(fd);
00238     return NULL;
00239   }
00240   if (get_string(inbuf, LINESIZE, fd) == NULL) {
00241     fclose(fd);
00242     return NULL;
00243   }
00244   if (sscanf(inbuf, "dim3=%d", &zsize) != 1) {
00245     fprintf(stderr, "avsplugin) Error reading dim3.\n");
00246     fclose(fd);
00247     return NULL;
00248   }
00249 
00250   /* Check the number of coordinates per point */
00251   if (get_string(inbuf, LINESIZE, fd) == NULL) {
00252     fclose(fd);
00253     return NULL;
00254   }
00255   if (sscanf(inbuf, "nspace=%d", &nspace) != 1) {
00256     fprintf(stderr, "avsplugin) Error reading nspace.\n");
00257     fclose(fd);
00258     return NULL;
00259   }
00260   if (nspace != 3) {
00261     fprintf(stderr, "avsplugin) Error: nspace must be 3.\n");
00262     fclose(fd);
00263     return NULL;
00264   }
00265 
00266   /* Find out how many values are stored for each point (the length of the
00267    * vector for the vector field) */
00268   if (get_string(inbuf, LINESIZE, fd) == NULL) {
00269     fclose(fd);
00270     return NULL;
00271   }
00272   if (sscanf(inbuf, "veclen=%d", &veclen) != 1) {
00273     fprintf(stderr, "avsplugin) Error reading veclen.\n");
00274     fclose(fd);
00275     return NULL;
00276   }
00277 
00278   /* Check that the data type is "float" */
00279   if (get_string(inbuf, LINESIZE, fd) == NULL) {
00280     fclose(fd);
00281     return NULL;
00282   }
00283   if (strncmp(inbuf, "data=float", 10) != 0) {
00284     fprintf(stderr, "avsplugin) Error reading data type.\n");
00285     fclose(fd);
00286     return NULL;
00287   }
00288 
00289   /* Check that the field type is "uniform" */
00290   if (get_string(inbuf, LINESIZE, fd) == NULL) {
00291     fclose(fd);
00292     return NULL;
00293   }
00294   if (strncmp(inbuf, "field=uniform", 13) != 0) {
00295     fprintf(stderr, "avsplugin) Error reading field type.\n");
00296     fclose(fd);
00297     return NULL;
00298   }
00299 
00300   /* Allocate space for the coordinate and variable information 
00301    * coord is deleted in this fuction, variable is deleted when the plugin
00302    * is closed.
00303    */
00304   coord = new datasource_t[ndim];
00305   variable = new datasource_t[veclen];
00306 
00307   /* Find the coordinate information */
00308   for (i = 0; i < ndim; i++) {
00309     if (get_string(inbuf, LINESIZE, fd) == NULL) {
00310       delete[] coord;
00311       fclose(fd);
00312       return NULL;
00313     }
00314     if ( (sscanf(inbuf, "coord %d", &coord_count) != 1) || (coord_count != i+1) ) {
00315     fprintf(stderr, "avsplugin) Error reading coord count.\n");
00316       delete[] coord;
00317       fclose(fd);
00318       return NULL;
00319     }
00320     if (read_datasource(inbuf, &coord[i])) {
00321       delete[] coord;
00322       fclose(fd);
00323       return NULL;
00324     }
00325   }
00326 
00327   /* XXX - Ignore the labels (should be used for vol dataname) */
00328   for (i = 0; i < veclen; i++) {
00329     if (get_string(inbuf, LINESIZE, fd) == NULL) {
00330       delete[] coord;
00331       fclose(fd);
00332       return NULL;
00333     }
00334   }
00335   
00336   /* Find the variable information */
00337   for (i = 0; i < veclen; i++) {
00338     if (get_string(inbuf, LINESIZE, fd) == NULL) {
00339       delete[] coord;
00340       fclose(fd);
00341       return NULL;
00342     }
00343     if ( (sscanf(inbuf, "variable %d", &var_count) != 1) || (var_count != i+1) ) {
00344       fprintf(stderr, "avsplugin) Error reading variable count.\n");
00345       delete[] coord;
00346       fclose(fd);
00347       return NULL;
00348     }
00349     if (read_datasource(inbuf, &variable[i])) {
00350       delete[] coord;
00351       fclose(fd);
00352       return NULL;
00353     }
00354   }
00355 
00356   /* Close the AVS file */
00357   fclose(fd);
00358   fd = NULL;
00359 
00360   /* Read the coordinate file(s) to find the origin and grid size 
00361    * XXX - this only works for "uniform" fields
00362    */
00363   for (i = 0; i < ndim; i++) {
00364     if (strcmp(current_file, coord[i].filename) != 0) {
00365       /* Close the old file if one was open, and open a new one */
00366       if (fd) {
00367         fclose(fd);
00368         fd = NULL;
00369       }
00370       strcpy(current_file, coord[i].filename); /* XXX - unsafe */
00371       fd = fopen(current_file, "rb");
00372       if (!fd) {
00373         fprintf(stderr, "avsplugin) Error opening file.\n");
00374         delete[] coord;
00375         return NULL;
00376       }
00377     }
00378     else {
00379       /* Return to the beginning of the file */
00380       rewind(fd);
00381     }
00382 
00383     /* Skip the "skip" lines */
00384     for (index = 0; index < coord[i].skip; index++) {
00385       if (fgets(inbuf, LINESIZE, fd) == NULL) {
00386         fprintf(stderr, "avsplugin) Error reading line.\n");
00387         fclose(fd);
00388         delete[] coord;
00389         return NULL;
00390       }
00391     }
00392 
00393     /* Skip the "offset" values */
00394     for (index = 0; index < coord[i].offset; index++) {
00395       if (fscanf(fd, " %f", &value) != 1) {
00396         fprintf(stderr, "avsplugin) Error skipping offset.\n");
00397         fclose(fd);
00398         delete[] coord;
00399         return NULL;
00400       }
00401     }
00402 
00403     /* Read the origin, skip "stride" values, and read the end */
00404     if (fscanf(fd, " %f", &value) != 1) {
00405       fprintf(stderr, "avsplugin) Error reading origin.\n");
00406       fclose(fd);
00407       delete[] coord;
00408       return NULL;
00409     }
00410     origin[i] = value;
00411     for (index = 0; index < coord[i].stride; index++) {
00412       if (fscanf(fd, " %f", &value) != 1) {
00413         fprintf(stderr, "avsplugin) Error skipping stride.\n");
00414         fclose(fd);
00415         delete[] coord;
00416         return NULL;
00417       }
00418     }
00419     gridlength[i] = value - origin[i];
00420   }
00421 
00422   /* Free the coordinates */
00423   delete[] coord;
00424   coord = NULL;
00425   fclose(fd);
00426 
00427   /* Allocate and initialize the avsfield structure */
00428   avsfield = new avsfield_t;
00429   avsfield->vol = NULL;
00430   *natoms = MOLFILE_NUMATOMS_NONE;
00431 
00432   /* AVS field files can have an arbitrary number of sets */
00433   avsfield->nsets = veclen;
00434   avsfield->vol = new molfile_volumetric_t[veclen];
00435   avsfield->data = variable;
00436 
00437   for (i = 0; i < veclen; i++) {
00438     /* strcpy(avsfield->vol[i].dataname, "AVS Field: "); */
00439     sprintf(avsfield->vol[i].dataname, "AVS Field: %d", i);
00440 
00441     avsfield->vol[i].origin[0] = origin[0];
00442     avsfield->vol[i].origin[1] = origin[1];
00443     avsfield->vol[i].origin[2] = origin[2];
00444 
00445     avsfield->vol[i].xaxis[0] = gridlength[0];
00446     avsfield->vol[i].xaxis[1] = 0;
00447     avsfield->vol[i].xaxis[2] = 0;
00448 
00449     avsfield->vol[i].yaxis[0] = 0;
00450     avsfield->vol[i].yaxis[1] = gridlength[1];
00451     avsfield->vol[i].yaxis[2] = 0;
00452 
00453     avsfield->vol[i].zaxis[0] = 0;
00454     avsfield->vol[i].zaxis[1] = 0;
00455     avsfield->vol[i].zaxis[2] = gridlength[2];
00456 
00457     avsfield->vol[i].xsize = xsize;
00458     avsfield->vol[i].ysize = ysize;
00459     avsfield->vol[i].zsize = zsize;
00460 
00461     avsfield->vol[i].has_color = 0;
00462   }
00463 
00464   return avsfield;
00465 }
00466 
00467 static int read_avsfield_metadata(void *v, int *nsets,
00468   molfile_volumetric_t **metadata) {
00469   avsfield_t *avsfield = (avsfield_t *)v;
00470   *nsets = avsfield->nsets;
00471   *metadata = avsfield->vol;
00472 
00473   return MOLFILE_SUCCESS;
00474 }
00475 
00476 static int read_avsfield_data(void *v, int set, float *datablock,
00477                          float *colorblock) {
00478   avsfield_t *avsfield = (avsfield_t *)v;
00479   int skip, offset, stride, count, ndata, index;
00480   float value, *cellIndex = datablock;
00481   char inbuf[LINESIZE];
00482   FILE *fd;
00483   
00484   fd = fopen(avsfield->data[set].filename, "rb");
00485   if (!fd) {
00486     fprintf(stderr, "avsplugin) Error opening file.\n");
00487     return MOLFILE_ERROR; 
00488   }
00489 
00490   skip = avsfield->data[set].skip;
00491   offset = avsfield->data[set].offset;
00492   stride = avsfield->data[set].stride;
00493 
00494   count = 0;
00495   ndata = avsfield->vol[0].xsize * avsfield->vol[0].ysize * avsfield->vol[0].zsize;
00496 
00497   /* Skip the "skip" lines */
00498   for (index = 0; index < skip; index++) {
00499     if (fgets(inbuf, LINESIZE, fd) == NULL) {
00500       fprintf(stderr, "avsplugin) Error skipping lines.\n");
00501       fclose(fd);
00502       return MOLFILE_ERROR;
00503     }
00504   }
00505 
00506   /* Skip the "offset" values */
00507   for (index = 0; index < offset; index++) {
00508     if (fscanf(fd, " %f", &value) != 1) {
00509       fprintf(stderr, "avsplugin) Error skipping offset.\n");
00510       fclose(fd);
00511       return MOLFILE_ERROR;
00512     }
00513   }
00514 
00515   while (count < ndata) {
00516     /* Read a value into the datablock and skip "stride" values */
00517     if (fscanf(fd, " %f", &value) != 1) {
00518       fprintf(stderr, "avsplugin) Error reading data.\n");
00519       fclose(fd);
00520       return MOLFILE_ERROR;
00521     }
00522     *cellIndex = value;
00523     cellIndex++;
00524     count++;
00525 
00526     for (index = 0; index < stride-1; index++) {
00527       if (fscanf(fd, " %f", &value) != 1) {
00528         fprintf(stderr, "avsplugin) Error skipping stride.\n");
00529         fclose(fd);
00530         return MOLFILE_ERROR;
00531       }
00532     }
00533   }
00534 
00535   fclose(fd);
00536   return MOLFILE_SUCCESS;
00537 }
00538 
00539 static void close_avsfield_read(void *v) {
00540   avsfield_t *avsfield = (avsfield_t *)v;
00541 
00542   if (avsfield->vol != NULL)
00543     delete [] avsfield->vol;
00544   if (avsfield->data != NULL)
00545     delete [] avsfield->data;
00546   delete avsfield;
00547 }
00548 
00549 /*
00550  * Initialization stuff here
00551  */
00552 static molfile_plugin_t plugin;
00553 
00554 VMDPLUGIN_API int VMDPLUGIN_init(void) { 
00555   memset(&plugin, 0, sizeof(plugin));
00556   plugin.abiversion = vmdplugin_ABIVERSION;
00557   plugin.type = MOLFILE_PLUGIN_TYPE;
00558   plugin.name = "fld";
00559   plugin.prettyname = "AVS Field";
00560   plugin.author = "Eamon Caddigan";
00561   plugin.majorv = 0;
00562   plugin.minorv = 5;
00563   plugin.is_reentrant = VMDPLUGIN_THREADUNSAFE;
00564   plugin.filename_extension = "fld";
00565   plugin.open_file_read = open_avsfield_read;
00566   plugin.read_volumetric_metadata = read_avsfield_metadata;
00567   plugin.read_volumetric_data = read_avsfield_data;
00568   plugin.close_file_read = close_avsfield_read;
00569 
00570   return VMDPLUGIN_SUCCESS; 
00571 }
00572 
00573 VMDPLUGIN_API int VMDPLUGIN_fini(void) { return VMDPLUGIN_SUCCESS; }
00574 
00575 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00576   (*cb)(v, (vmdplugin_t *)&plugin);
00577   return VMDPLUGIN_SUCCESS;
00578 }
00579 

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