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 #include <stdlib.h>
00027 #include <stdio.h>
00028 #include <ctype.h>
00029 #include <math.h>
00030 #include <string.h>
00031
00032 #if defined(_AIX)
00033 #include <strings.h>
00034 #endif
00035
00036 #if defined(WIN32) || defined(WIN64)
00037 #define strcasecmp stricmp
00038 #define strncasecmp strnicmp
00039 #endif
00040
00041 #include "molfile_plugin.h"
00042 #include "endianswap.h"
00043
00044 #define LINESIZE 85
00045
00046 typedef struct {
00047 FILE *fd;
00048 int nsets;
00049 molfile_volumetric_t *vol;
00050 float scale;
00051
00052 int doswap;
00053 } uhbd_t;
00054
00055
00056
00057 static char *uhbdgets(char *s, int n, FILE *stream, const char *msg) {
00058 char *returnVal;
00059
00060 if (feof(stream)) {
00061 printf("%s", msg);
00062 printf("uhbdplugin) Unexpected end-of-file.\n");
00063 return NULL;
00064 } else if (ferror(stream)) {
00065 printf("%s", msg);
00066 printf("uhbdplugin) Error reading file.\n");
00067 return NULL;
00068 } else {
00069 returnVal = fgets(s, n, stream);
00070 if (returnVal == NULL) {
00071 printf("%s", msg);
00072 printf("uhbdplugin) Encountered EOF or error reading line.\n");
00073 }
00074 }
00075
00076 return returnVal;
00077 }
00078
00079 static void *open_uhbd_read(const char *filepath, const char *filetype,
00080 int *natoms) {
00081 FILE *fd;
00082 uhbd_t *uhbd;
00083 char inbuf[LINESIZE];
00084 int xsize, ysize, zsize;
00085 float orig[3], ra, o[3], s[3];
00086 int headersize = 0;
00087 int doswap = 0;
00088 float scale=0;
00089
00090 if ((fd = fopen(filepath, "rb")) == NULL) {
00091 printf("uhbdplugin) Error opening file.\n");
00092 return NULL;
00093 }
00094
00095
00096
00097 fread(&headersize, sizeof(int), 1, fd);
00098 if (headersize == 160) {
00099 printf("uhbdplugin) Detected binary .grd file in native endian\n");
00100 doswap = 0;
00101 } else {
00102 swap4_unaligned(&headersize, 1);
00103 if (headersize == 160) {
00104 printf("uhbdplugin) Detected binary .grd file in opposite endian\n");
00105 doswap = 1;
00106 } else {
00107 headersize = 0;
00108 }
00109 }
00110 if (headersize == 160) {
00111 int iparams[8];
00112 float fparams[4];
00113
00114
00115 char buf[164];
00116 if (fread(buf, 1, 160, fd) != 160) {
00117 fprintf(stderr, "uhbdplugin) Error: incomplete header in .grd file.\n");
00118 fclose(fd);
00119 return NULL;
00120 }
00121
00122
00123
00124 memcpy(&scale, buf + 72, sizeof(float));
00125 memcpy(iparams, buf + 72 + 8, 32);
00126 memcpy(fparams, buf + 72 + 40, 16);
00127 if (doswap) {
00128 swap4_unaligned(&scale, 1);
00129 swap4_unaligned(iparams, 8);
00130 swap4_unaligned(fparams, 4);
00131 }
00132 xsize = iparams[5];
00133 ysize = iparams[6];
00134 zsize = iparams[7];
00135 ra = fparams[0];
00136 orig[0] = fparams[1];
00137 orig[1] = fparams[2];
00138 orig[2] = fparams[3];
00139
00140 } else {
00141 rewind(fd);
00142
00143 if (uhbdgets(inbuf, LINESIZE, fd,
00144 "uhbdplugin) error while skipping header lines\n") == NULL)
00145 return NULL;
00146 if (uhbdgets(inbuf, LINESIZE, fd,
00147 "uhbdplugin) error while skipping header lines\n") == NULL)
00148 return NULL;
00149
00150
00151 if (uhbdgets(inbuf, LINESIZE, fd,
00152 "uhbdplugin) error while getting grid dimensions\n") == NULL) {
00153 return NULL;
00154 }
00155 if (sscanf(inbuf, "%d %d %d %e %e %e %e", &xsize, &ysize, &zsize, &ra, orig, orig+1, orig+2) != 7) {
00156 printf("uhbdplugin) Error reading grid dimensions, spacing and origin.\n");
00157 return NULL;
00158 }
00159 if (uhbdgets(inbuf, LINESIZE, fd,
00160 "uhbdplugin) error while skipping header lines\n") == NULL)
00161 return NULL;
00162 if (uhbdgets(inbuf, LINESIZE, fd,
00163 "uhbdplugin) error while skipping header lines\n") == NULL)
00164 return NULL;
00165 }
00166
00167
00168 uhbd = new uhbd_t;
00169 uhbd->fd = fd;
00170 uhbd->vol = NULL;
00171 *natoms = MOLFILE_NUMATOMS_NONE;
00172 uhbd->nsets = 1;
00173 uhbd->scale = scale;
00174 uhbd->doswap = doswap;
00175
00176 uhbd->vol = new molfile_volumetric_t[1];
00177 strcpy(uhbd->vol[0].dataname,
00178 headersize ? "UHBD binary Electron Density Map"
00179 : "UHBD ascii Electron Density Map");
00180
00181
00182 for (int i=0; i<3; i++) {
00183 uhbd->vol[0].origin[i] = orig[i] + ra;
00184 o[i] = uhbd->vol[0].origin[i];
00185 }
00186
00187 uhbd->vol[0].xaxis[0] = ra * (xsize-1);
00188 uhbd->vol[0].xaxis[1] = 0;
00189 uhbd->vol[0].xaxis[2] = 0;
00190
00191 uhbd->vol[0].yaxis[0] = 0;
00192 uhbd->vol[0].yaxis[1] = ra * (ysize-1);
00193 uhbd->vol[0].yaxis[2] = 0;
00194
00195 uhbd->vol[0].zaxis[0] = 0;
00196 uhbd->vol[0].zaxis[1] = 0;
00197 uhbd->vol[0].zaxis[2] = ra * (zsize-1);
00198
00199 s[0] = uhbd->vol[0].xaxis[0];
00200 s[1] = uhbd->vol[0].yaxis[1];
00201 s[2] = uhbd->vol[0].zaxis[2];
00202
00203 uhbd->vol[0].xsize = xsize;
00204 uhbd->vol[0].ysize = ysize;
00205 uhbd->vol[0].zsize = zsize;
00206
00207
00208 uhbd->vol[0].has_color = 0;
00209
00210 return uhbd;
00211 }
00212
00213 static int read_uhbd_metadata(void *v, int *nsets,
00214 molfile_volumetric_t **metadata) {
00215 uhbd_t *uhbd = (uhbd_t *)v;
00216 *nsets = uhbd->nsets;
00217 *metadata = uhbd->vol;
00218
00219 return MOLFILE_SUCCESS;
00220 }
00221
00222 static int read_uhbd_data(void *v, int set, float *datablock,
00223 float *colorblock) {
00224 uhbd_t *uhbd = (uhbd_t *)v;
00225 FILE *fd = uhbd->fd;
00226 char inbuf[LINESIZE];
00227 float grid[6];
00228 int z, xsize, ysize, zsize, xysize, count, count2, total, i;
00229
00230 xsize = uhbd->vol[0].xsize;
00231 ysize = uhbd->vol[0].ysize;
00232 zsize = uhbd->vol[0].zsize;
00233 xysize = xsize * ysize;
00234 total = xysize * zsize;
00235
00236 if (uhbd->scale) {
00237 int headerblock[6];
00238
00239
00240
00241
00242
00243 for (z=0; z<zsize; z++) {
00244 if (fread(headerblock, sizeof(int), 6, fd) != 6) {
00245 fprintf(stderr, "uhbdplugin) Error reading header block in binary uhbd file\n");
00246 return MOLFILE_ERROR;
00247 }
00248
00249 if (fread(datablock + z*xysize, sizeof(float), xysize, fd) != xysize) {
00250 fprintf(stderr, "uhbdplugin) Error reading data block in binary uhbd file\n");
00251 return MOLFILE_ERROR;
00252 }
00253
00254 fseek(fd, 4, SEEK_CUR);
00255 }
00256 if (uhbd->doswap) {
00257 swap4_aligned(datablock, total);
00258 }
00259 return MOLFILE_SUCCESS;
00260 }
00261
00262
00263 for (z = 0; z < zsize; z++) {
00264
00265 if (uhbdgets(inbuf, LINESIZE, fd,
00266 "uhbdplugin) error while getting density plane indices\n") == NULL)
00267 return MOLFILE_ERROR;
00268
00269
00270 for (count = 0; count < xysize/6; count++) {
00271 if (uhbdgets(inbuf, LINESIZE, fd,
00272 "uhbdplugin) error while getting density values\n") == NULL)
00273 return MOLFILE_ERROR;
00274
00275 if (sscanf(inbuf, "%e %e %e %e %e %e", &grid[0], &grid[1], &grid[2], &grid[3], &grid[4], &grid[5]) != 6) {
00276 printf("uhbdplugin) Error reading grid data.\n");
00277 return MOLFILE_ERROR;
00278 }
00279
00280 for (i = 0; i < 6; i++) {
00281 datablock[i + count*6 + z*xysize] = grid[i];
00282 }
00283 }
00284
00285 if ((xysize%6) != 0) {
00286 if (uhbdgets(inbuf, LINESIZE, fd,
00287 "uhbdplugin) error reading data elements modulo 6\n") == NULL)
00288 return MOLFILE_ERROR;
00289
00290 count2 = sscanf(inbuf, "%e %e %e %e %e %e", &grid[0], &grid[1], &grid[2], &grid[3], &grid[4], &grid[5]);
00291 if (count2 != (xysize%6)) {
00292 printf("uhbdplugin) Error: incorrect number of data points.\n");
00293 return MOLFILE_ERROR;
00294 }
00295
00296 for (i = 0; i < count2; i++) {
00297 datablock[i + (count+1)*6 + z*xysize] = grid[i];
00298 }
00299 }
00300 }
00301
00302 return MOLFILE_SUCCESS;
00303 }
00304
00305
00306 static void close_uhbd_read(void *v) {
00307 uhbd_t *uhbd = (uhbd_t *)v;
00308
00309 fclose(uhbd->fd);
00310 if (uhbd->vol != NULL)
00311 delete [] uhbd->vol;
00312 delete uhbd;
00313 }
00314
00315
00316
00317
00318
00319 static molfile_plugin_t plugin;
00320
00321 VMDPLUGIN_API int VMDPLUGIN_init(void) {
00322 memset(&plugin, 0, sizeof(molfile_plugin_t));
00323 plugin.abiversion = vmdplugin_ABIVERSION;
00324 plugin.type = MOLFILE_PLUGIN_TYPE;
00325 plugin.name = "uhbd";
00326 plugin.prettyname = "UHBD Grid";
00327 plugin.author = "Alexander Spaar, Justin Gullingsrud";
00328 plugin.majorv = 0;
00329 plugin.minorv = 5;
00330 plugin.is_reentrant = VMDPLUGIN_THREADSAFE;
00331 plugin.filename_extension = "uhbdgrd,grd";
00332 plugin.open_file_read = open_uhbd_read;
00333 plugin.read_volumetric_metadata = read_uhbd_metadata;
00334 plugin.read_volumetric_data = read_uhbd_data;
00335 plugin.close_file_read = close_uhbd_read;
00336 return VMDPLUGIN_SUCCESS;
00337 }
00338
00339
00340 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00341 (*cb)(v, (vmdplugin_t *)&plugin);
00342 return VMDPLUGIN_SUCCESS;
00343 }
00344
00345 VMDPLUGIN_API int VMDPLUGIN_fini(void) { return VMDPLUGIN_SUCCESS; }
00346