00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <math.h>
00031 #include <string.h>
00032
00033 #ifndef M_PI
00034 #define M_PI 3.14159265358979323846
00035 #endif
00036
00037 #include "molfile_plugin.h"
00038 #include "endianswap.h"
00039
00040 #define CCP4HDSIZE 1024
00041
00042 typedef struct {
00043 FILE *fd;
00044 int nsets;
00045 int swap;
00046 int xyz2crs[3];
00047 long dataOffset;
00048 molfile_volumetric_t *vol;
00049 } ccp4_t;
00050
00051 static void *open_ccp4_read(const char *filepath, const char *filetype,
00052 int *natoms) {
00053 FILE *fd;
00054 ccp4_t *ccp4;
00055 char mapString[4], symData[81];
00056 int origin[3], extent[3], grid[3], crs2xyz[3], mode, symBytes;
00057 int swap, i, xIndex, yIndex, zIndex;
00058 long dataOffset, filesize;
00059 float cellDimensions[3], cellAngles[3], xaxis[3], yaxis[3], zaxis[3];
00060 float alpha, beta, gamma, xScale, yScale, zScale, z1, z2, z3;
00061
00062 fd = fopen(filepath, "rb");
00063 if (!fd) {
00064 printf("ccp4plugin) Error opening file %s\n", filepath);
00065 return NULL;
00066 }
00067
00068 if ( (fread(extent, sizeof(int), 3, fd) != 3) ||
00069 (fread(&mode, sizeof(int), 1, fd) != 1) ||
00070 (fread(origin, sizeof(int), 3, fd) != 3) ||
00071 (fread(grid, sizeof(int), 3, fd) != 3) ||
00072 (fread(cellDimensions, sizeof(float), 3, fd) != 3) ||
00073 (fread(cellAngles, sizeof(float), 3, fd) != 3) ||
00074 (fread(crs2xyz, sizeof(int), 3, fd) != 3) ) {
00075 printf("ccp4plugin) Error: Improperly formatted line.\n");
00076 return NULL;
00077 }
00078
00079
00080 fseek(fd, 92, SEEK_SET);
00081 if ((fread(&symBytes, sizeof(int), 1, fd) != 1) ) {
00082 printf("ccp4plugin) Error: Failed reading symmetry bytes record.\n");
00083 return NULL;
00084 }
00085
00086
00087 fseek(fd, 208, SEEK_SET);
00088 if ( (fgets(mapString, 4, fd) == NULL) ||
00089 (strcmp(mapString, "MAP") != 0) ) {
00090 printf("ccp4plugin) Error: 'MAP' string missing, not a valid CCP4 file.\n");
00091 return NULL;
00092 }
00093
00094 swap = 0;
00095
00096 if (mode != 2) {
00097
00098 swap4_aligned(&mode, 1);
00099 if (mode != 2) {
00100 printf("ccp4plugin) Error: Non-real (32-bit float) data types are unsupported.\n");
00101 return NULL;
00102 } else {
00103 swap = 1;
00104 }
00105 }
00106
00107
00108 if (swap == 1) {
00109 swap4_aligned(extent, 3);
00110 swap4_aligned(origin, 3);
00111 swap4_aligned(grid, 3);
00112 swap4_aligned(cellDimensions, 3);
00113 swap4_aligned(cellAngles, 3);
00114 swap4_aligned(crs2xyz, 3);
00115 swap4_aligned(&symBytes, 1);
00116 }
00117
00118
00119 #if 1
00120 printf("ccp4plugin) extent: %d x %d x %d\n", extent[0], extent[1], extent[2]);
00121 printf("ccp4plugin) origin: %d x %d x %d\n", origin[0], origin[1], origin[2]);
00122 printf("ccp4plugin) grid: %d x %d x %d\n", grid[0], grid[1], grid[2]);
00123 printf("ccp4plugin) celldim: %f x %f x %f\n",
00124 cellDimensions[0], cellDimensions[1], cellDimensions[2]);
00125 printf("cpp4plugin)cellangles: %f, %f, %f\n",
00126 cellAngles[0], cellAngles[1], cellAngles[2]);
00127 printf("ccp4plugin) crs2xyz: %d %d %d\n",
00128 crs2xyz[0], crs2xyz[1], crs2xyz[2]);
00129 printf("ccp4plugin) symBytes: %d\n", symBytes);
00130 #endif
00131
00132
00133
00134
00135 fseek(fd, 0, SEEK_END);
00136 filesize = ftell(fd);
00137 dataOffset = filesize - 4*(extent[0]*extent[1]*extent[2]);
00138 if (dataOffset != (CCP4HDSIZE + symBytes)) {
00139 if (dataOffset == CCP4HDSIZE) {
00140
00141 printf("ccp4plugin) Warning: file contains bogus symmetry record.\n");
00142 symBytes = 0;
00143 } else if (dataOffset < CCP4HDSIZE) {
00144 printf("ccp4plugin) Error: File appears truncated and doesn't match header.\n");
00145 return NULL;
00146 } else if ((dataOffset > CCP4HDSIZE) && (dataOffset < (1024*1024))) {
00147
00148
00149 dataOffset = CCP4HDSIZE + symBytes;
00150 printf("ccp4plugin) Warning: File is larger than expected and doesn't match header.\n");
00151 printf("ccp4plugin) Warning: Continuing file load, good luck!\n");
00152 } else {
00153 printf("ccp4plugin) Error: File is MUCH larger than expected and doesn't match header.\n");
00154 return NULL;
00155 }
00156 }
00157
00158
00159 if (symBytes != 0) {
00160 printf("ccp4plugin) Symmetry records found:\n");
00161 fseek(fd, CCP4HDSIZE, SEEK_SET);
00162 for (i = 0; i < symBytes/80; i++) {
00163 fgets(symData, 81, fd);
00164 printf("ccp4plugin) %s\n", symData);
00165 }
00166 }
00167
00168
00169 if (grid[0] == 0 && extent[0] > 0) {
00170 grid[0] = extent[0] - 1;
00171 printf("ccp4plugin) Warning: Fixed X interval count\n");
00172 }
00173 if (grid[1] == 0 && extent[1] > 0) {
00174 grid[1] = extent[1] - 1;
00175 printf("ccp4plugin) Warning: Fixed Y interval count\n");
00176 }
00177 if (grid[2] == 0 && extent[2] > 0) {
00178 grid[2] = extent[2] - 1;
00179 printf("ccp4plugin) Warning: Fixed Z interval count\n");
00180 }
00181
00182
00183
00184 ccp4 = new ccp4_t;
00185 ccp4->fd = fd;
00186 ccp4->vol = NULL;
00187 *natoms = MOLFILE_NUMATOMS_NONE;
00188 ccp4->nsets = 1;
00189 ccp4->swap = swap;
00190 ccp4->dataOffset = dataOffset;
00191
00192 ccp4->vol = new molfile_volumetric_t[1];
00193 strcpy(ccp4->vol[0].dataname, "CCP4 Electron Density Map");
00194
00195
00196 if (crs2xyz[0] == 0 && crs2xyz[1] == 0 && crs2xyz[2] == 0) {
00197 printf("ccp4plugin) Warning: All crs2xyz records are zero.\n");
00198 printf("ccp4plugin) Warning: Setting crs2xyz to 1, 2, 3\n");
00199 crs2xyz[0] = 1;
00200 crs2xyz[0] = 2;
00201 crs2xyz[0] = 3;
00202 }
00203
00204 ccp4->xyz2crs[crs2xyz[0]-1] = 0;
00205 ccp4->xyz2crs[crs2xyz[1]-1] = 1;
00206 ccp4->xyz2crs[crs2xyz[2]-1] = 2;
00207 xIndex = ccp4->xyz2crs[0];
00208 yIndex = ccp4->xyz2crs[1];
00209 zIndex = ccp4->xyz2crs[2];
00210
00211
00212 alpha = (M_PI / 180.0) * cellAngles[0];
00213 beta = (M_PI / 180.0) * cellAngles[1];
00214 gamma = (M_PI / 180.0) * cellAngles[2];
00215
00216 if (cellDimensions[0] == 0.0 &&
00217 cellDimensions[1] == 0.0 &&
00218 cellDimensions[2] == 0.0) {
00219 printf("ccp4plugin) Warning: Cell dimensions are all zero.\n");
00220 printf("ccp4plugin) Warning: Setting to 1.0, 1.0, 1.0 for viewing.\n");
00221 printf("ccp4plugin) Warning: Map file will not align with other structures.\n");
00222 cellDimensions[0] = 1.0;
00223 cellDimensions[1] = 1.0;
00224 cellDimensions[2] = 1.0;
00225 }
00226
00227
00228 xScale = cellDimensions[0] / grid[0];
00229 yScale = cellDimensions[1] / grid[1];
00230 zScale = cellDimensions[2] / grid[2];
00231
00232
00233 xaxis[0] = xScale;
00234 xaxis[1] = 0;
00235 xaxis[2] = 0;
00236
00237 yaxis[0] = cos(gamma) * yScale;
00238 yaxis[1] = sin(gamma) * yScale;
00239 yaxis[2] = 0;
00240
00241 z1 = cos(beta);
00242 z2 = (cos(alpha) - cos(beta)*cos(gamma)) / sin(gamma);
00243 z3 = sqrt(1.0 - z1*z1 - z2*z2);
00244 zaxis[0] = z1 * zScale;
00245 zaxis[1] = z2 * zScale;
00246 zaxis[2] = z3 * zScale;
00247
00248 ccp4->vol[0].origin[0] = xaxis[0] * origin[xIndex] +
00249 yaxis[0] * origin[yIndex] +
00250 zaxis[0] * origin[zIndex];
00251 ccp4->vol[0].origin[1] = yaxis[1] * origin[yIndex] +
00252 zaxis[1] * origin[zIndex];
00253 ccp4->vol[0].origin[2] = zaxis[2] * origin[zIndex];
00254
00255 ccp4->vol[0].xaxis[0] = xaxis[0] * (extent[xIndex]-1);
00256 ccp4->vol[0].xaxis[1] = 0;
00257 ccp4->vol[0].xaxis[2] = 0;
00258
00259 ccp4->vol[0].yaxis[0] = yaxis[0] * (extent[yIndex]-1);
00260 ccp4->vol[0].yaxis[1] = yaxis[1] * (extent[yIndex]-1);
00261 ccp4->vol[0].yaxis[2] = 0;
00262
00263 ccp4->vol[0].zaxis[0] = zaxis[0] * (extent[zIndex]-1);
00264 ccp4->vol[0].zaxis[1] = zaxis[1] * (extent[zIndex]-1);
00265 ccp4->vol[0].zaxis[2] = zaxis[2] * (extent[zIndex]-1);
00266
00267 ccp4->vol[0].xsize = extent[xIndex];
00268 ccp4->vol[0].ysize = extent[yIndex];
00269 ccp4->vol[0].zsize = extent[zIndex];
00270
00271 ccp4->vol[0].has_color = 0;
00272
00273 return ccp4;
00274 }
00275
00276 static int read_ccp4_metadata(void *v, int *nsets,
00277 molfile_volumetric_t **metadata) {
00278 ccp4_t *ccp4 = (ccp4_t *)v;
00279 *nsets = ccp4->nsets;
00280 *metadata = ccp4->vol;
00281
00282 return MOLFILE_SUCCESS;
00283 }
00284
00285 static int read_ccp4_data(void *v, int set, float *datablock,
00286 float *colorblock) {
00287 ccp4_t *ccp4 = (ccp4_t *)v;
00288 float *rowdata;
00289 int x, y, z, xSize, ySize, zSize, xySize, extent[3], coord[3];
00290 FILE *fd = ccp4->fd;
00291
00292 xSize = ccp4->vol[0].xsize;
00293 ySize = ccp4->vol[0].ysize;
00294 zSize = ccp4->vol[0].zsize;
00295 xySize = xSize * ySize;
00296
00297
00298
00299 extent[ccp4->xyz2crs[0]] = xSize;
00300 extent[ccp4->xyz2crs[1]] = ySize;
00301 extent[ccp4->xyz2crs[2]] = zSize;
00302
00303 rowdata = new float[extent[0]];
00304
00305 fseek(fd, ccp4->dataOffset, SEEK_SET);
00306
00307 for (coord[2] = 0; coord[2] < extent[2]; coord[2]++) {
00308 for (coord[1] = 0; coord[1] < extent[1]; coord[1]++) {
00309
00310
00311 if (feof(fd)) {
00312 printf("ccp4plugin) Unexpected end-of-file.\n");
00313 return MOLFILE_ERROR;
00314 }
00315 if (ferror(fd)) {
00316 printf("ccp4plugin) Problem reading the file.\n");
00317 return MOLFILE_ERROR;
00318 }
00319 if ( fread(rowdata, sizeof(float), extent[0], fd) != extent[0] ) {
00320 printf("ccp4plugin) Error reading data row.\n");
00321 return MOLFILE_ERROR;
00322 }
00323
00324 for (coord[0] = 0; coord[0] < extent[0]; coord[0]++) {
00325 x = coord[ccp4->xyz2crs[0]];
00326 y = coord[ccp4->xyz2crs[1]];
00327 z = coord[ccp4->xyz2crs[2]];
00328 datablock[x + y*xSize + z*xySize] = rowdata[coord[0]];
00329 }
00330 }
00331 }
00332
00333 if (ccp4->swap == 1)
00334 swap4_aligned(datablock, xySize * zSize);
00335
00336 delete [] rowdata;
00337
00338 return MOLFILE_SUCCESS;
00339 }
00340
00341 static void close_ccp4_read(void *v) {
00342 ccp4_t *ccp4 = (ccp4_t *)v;
00343
00344 fclose(ccp4->fd);
00345 delete [] ccp4->vol;
00346 delete ccp4;
00347 }
00348
00349
00350
00351
00352 static molfile_plugin_t plugin;
00353
00354 VMDPLUGIN_API int VMDPLUGIN_init(void) {
00355 memset(&plugin, 0, sizeof(molfile_plugin_t));
00356 plugin.abiversion = vmdplugin_ABIVERSION;
00357 plugin.type = MOLFILE_PLUGIN_TYPE;
00358 plugin.name = "ccp4";
00359 plugin.prettyname = "CCP4, MRC Density Map";
00360 plugin.author = "Eamon Caddigan, John Stone";
00361 plugin.majorv = 1;
00362 plugin.minorv = 2;
00363 plugin.is_reentrant = VMDPLUGIN_THREADSAFE;
00364 plugin.filename_extension = "ccp4,mrc,map";
00365 plugin.open_file_read = open_ccp4_read;
00366 plugin.read_volumetric_metadata = read_ccp4_metadata;
00367 plugin.read_volumetric_data = read_ccp4_data;
00368 plugin.close_file_read = close_ccp4_read;
00369 return VMDPLUGIN_SUCCESS;
00370 }
00371
00372
00373 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00374 (*cb)(v, (vmdplugin_t *)&plugin);
00375 return VMDPLUGIN_SUCCESS;
00376 }
00377
00378 VMDPLUGIN_API int VMDPLUGIN_fini(void) { return VMDPLUGIN_SUCCESS; }