00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdlib.h>
00019 #include <stdio.h>
00020 #include <string.h>
00021 #include <limits.h>
00022
00023 #include "molfile_plugin.h"
00024
00025 #if INT_MAX == 2147483647
00026 typedef int namdbin_int32;
00027 #elif SHRT_MAX == 2147483647
00028 typedef short namdbin_int32;
00029 #elif LONG_MAX == 2147483647
00030 typedef long namdbin_int32;
00031 #endif
00032
00033 #define BLOCK 500
00034
00035 typedef struct {
00036 double xyz[3*BLOCK];
00037 FILE *fd;
00038 int numatoms;
00039 int wrongendian;
00040 } namdbinhandle;
00041
00042 static void *open_namdbin_read(const char *path, const char *filetype,
00043 int *natoms) {
00044 namdbinhandle *namdbin;
00045 FILE *fd;
00046 int numatoms;
00047 namdbin_int32 filen;
00048 char lenbuf[4];
00049 char tmpc;
00050
00051 namdbin = (namdbinhandle *)malloc(sizeof(namdbinhandle));
00052 if (!namdbin) {
00053 fprintf(stderr, "Unable to allocate space for read buffer.\n");
00054 return NULL;
00055 }
00056 memset(namdbin, 0, sizeof(namdbinhandle));
00057
00058 fd = fopen(path, "rb");
00059 if (!fd) {
00060 fprintf(stderr, "Could not open file '%s' for reading.\n", path);
00061 free(namdbin);
00062 return NULL;
00063 }
00064 fseek(fd,0,SEEK_END);
00065 numatoms = (ftell(fd)-4)/24;
00066 if (numatoms < 1) {
00067 fprintf(stderr, "File '%s' is too short.\n", path);
00068 fclose(fd);
00069 free(namdbin);
00070 return NULL;
00071 }
00072 fseek(fd,0,SEEK_SET);
00073 fread(&filen, sizeof(namdbin_int32), 1, fd);
00074 if (filen != numatoms) {
00075 namdbin->wrongendian = 1;
00076 memcpy(lenbuf, (const char *)&filen, 4);
00077 tmpc = lenbuf[0]; lenbuf[0] = lenbuf[3]; lenbuf[3] = tmpc;
00078 tmpc = lenbuf[1]; lenbuf[1] = lenbuf[2]; lenbuf[2] = tmpc;
00079 memcpy((char *)&filen, lenbuf, 4);
00080 }
00081 if (filen != numatoms) {
00082 fprintf(stderr, "Inconsistent atom count in file '%s'.\n", path);
00083 fclose(fd);
00084 free(namdbin);
00085 return NULL;
00086 }
00087 if ( namdbin->wrongendian ) {
00088 fprintf(stderr, "File '%s' appears to be other-endian.\n", path);
00089 }
00090 namdbin->fd = fd;
00091 namdbin->numatoms = numatoms;
00092 *natoms = namdbin->numatoms;
00093 return namdbin;
00094 }
00095
00096 static int read_next_timestep(void *v, int natoms, molfile_timestep_t *ts) {
00097 namdbinhandle *namdbin;
00098 int i, numatoms;
00099 char *cdata;
00100
00101 namdbin = (namdbinhandle *)v;
00102 if (!namdbin->fd)
00103 return MOLFILE_ERROR;
00104
00105 numatoms = namdbin->numatoms;
00106
00107 for (i=0; i<namdbin->numatoms; i+=BLOCK) {
00108 int j, n;
00109 n = namdbin->numatoms - i;
00110 if ( n > BLOCK ) n = BLOCK;
00111
00112 if (fread(namdbin->xyz, sizeof(double), 3*n, namdbin->fd) != (size_t)(3*n)) {
00113 fprintf(stderr, "Failure reading data from NAMD binary file.\n");
00114 return MOLFILE_ERROR;
00115 }
00116
00117 if (namdbin->wrongendian) {
00118 if ( ! i ) fprintf(stderr, "Converting other-endian data from NAMD binary file.\n");
00119 cdata = (char *) namdbin->xyz;
00120 for ( j=0; j<3*n; ++j, cdata+=8 ) {
00121 char tmp0, tmp1, tmp2, tmp3;
00122 tmp0 = cdata[0]; tmp1 = cdata[1];
00123 tmp2 = cdata[2]; tmp3 = cdata[3];
00124 cdata[0] = cdata[7]; cdata[1] = cdata[6];
00125 cdata[2] = cdata[5]; cdata[3] = cdata[4];
00126 cdata[7] = tmp0; cdata[6] = tmp1;
00127 cdata[5] = tmp2; cdata[4] = tmp3;
00128 }
00129 }
00130
00131 if (ts) {
00132 for (j=0; j<n; ++j) {
00133 ts->coords[3L*(i+j) ] = namdbin->xyz[3*j ];
00134 ts->coords[3L*(i+j)+1] = namdbin->xyz[3*j+1];
00135 ts->coords[3L*(i+j)+2] = namdbin->xyz[3*j+2];
00136 }
00137 }
00138
00139 }
00140
00141
00142
00143 fclose(namdbin->fd);
00144 namdbin->fd = NULL;
00145
00146 return MOLFILE_SUCCESS;
00147 }
00148
00149 static void close_file_read(void *v) {
00150 namdbinhandle *namdbin = (namdbinhandle *)v;
00151 if (namdbin->fd)
00152 fclose(namdbin->fd);
00153 free(namdbin);
00154 }
00155
00156 static void *open_namdbin_write(const char *path, const char *filetype,
00157 int natoms) {
00158 namdbinhandle *namdbin;
00159 FILE *fd;
00160
00161 namdbin = (namdbinhandle *)malloc(sizeof(namdbinhandle));
00162 if (!namdbin) {
00163 fprintf(stderr, "Unable to allocate space for write buffer.\n");
00164 return NULL;
00165 }
00166
00167 fd = fopen(path, "wb");
00168 if (!fd) {
00169 fprintf(stderr, "Could not open file %s for writing\n", path);
00170 free(namdbin);
00171 return NULL;
00172 }
00173
00174 namdbin->fd = fd;
00175 namdbin->numatoms = natoms;
00176 return namdbin;
00177 }
00178
00179 static int write_timestep(void *v, const molfile_timestep_t *ts) {
00180
00181 int i;
00182 namdbin_int32 myint;
00183 namdbinhandle *namdbin = (namdbinhandle *)v;
00184
00185 if (!namdbin->fd)
00186 return MOLFILE_ERROR;
00187
00188 myint = (namdbin_int32)namdbin->numatoms;
00189 fwrite(&myint, 4, 1, namdbin->fd);
00190
00191 for (i=0; i<namdbin->numatoms; i+=BLOCK) {
00192 double *tmp = namdbin->xyz;
00193 int j, n;
00194 n = namdbin->numatoms - i;
00195 if ( n > BLOCK ) n = BLOCK;
00196 for (j=0; j<n; ++j) {
00197 tmp[3*j ] = ts->coords[3L*(i+j) ];
00198 tmp[3*j+1] = ts->coords[3L*(i+j)+1];
00199 tmp[3*j+2] = ts->coords[3L*(i+j)+2];
00200 }
00201 if (fwrite(tmp, sizeof(double), 3*n, namdbin->fd) != 3*n) {
00202 fprintf(stderr, "Error writing namd binary file\n");
00203 return MOLFILE_ERROR;
00204 }
00205 }
00206
00207
00208
00209
00210 fclose(namdbin->fd);
00211 namdbin->fd = NULL;
00212
00213 return MOLFILE_SUCCESS;
00214 }
00215
00216 static void close_file_write(void *v) {
00217 namdbinhandle *namdbin = (namdbinhandle *)v;
00218 if (namdbin->fd)
00219 fclose(namdbin->fd);
00220 free(namdbin);
00221 }
00222
00223
00224
00225
00226
00227 static molfile_plugin_t plugin;
00228
00229 VMDPLUGIN_API int VMDPLUGIN_init() {
00230 memset(&plugin, 0, sizeof(molfile_plugin_t));
00231 plugin.abiversion = vmdplugin_ABIVERSION;
00232 plugin.type = MOLFILE_PLUGIN_TYPE;
00233 plugin.name = "namdbin";
00234 plugin.prettyname = "NAMD Binary Coordinates";
00235 plugin.author = "James Phillips, Justin Gullingsrud";
00236 plugin.majorv = 0;
00237 plugin.minorv = 2;
00238 plugin.is_reentrant = VMDPLUGIN_THREADSAFE;
00239 plugin.filename_extension = "coor";
00240 plugin.open_file_read = open_namdbin_read;
00241 plugin.read_next_timestep = read_next_timestep;
00242 plugin.close_file_read = close_file_read;
00243 plugin.open_file_write = open_namdbin_write;
00244 plugin.write_timestep = write_timestep;
00245 plugin.close_file_write = close_file_write;
00246 return VMDPLUGIN_SUCCESS;
00247 }
00248
00249 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00250 (*cb)(v, (vmdplugin_t *)&plugin);
00251 return VMDPLUGIN_SUCCESS;
00252 }
00253
00254 VMDPLUGIN_API int VMDPLUGIN_fini() {
00255 return VMDPLUGIN_SUCCESS;
00256 }
00257
00258
00259 #ifdef TEST_NAMDBINPLUGIN
00260
00261 int main(int argc, char *argv[]) {
00262 molfile_header_t header;
00263 molfile_timestep_t timestep;
00264 void *v;
00265 int i;
00266
00267 while (--argc) {
00268 ++argv;
00269 v = open_namdbin_read(*argv, &header);
00270 if (!v) {
00271 fprintf(stderr, "open_namdbin_read failed for file %s\n", *argv);
00272 return 1;
00273 }
00274 timestep.coords = (float *)malloc(3*sizeof(float)*header.numatoms);
00275 for (i=0; i<header.numsteps; i++) {
00276 int rc = read_next_timestep(v, ×tep);
00277 if (rc) {
00278 fprintf(stderr, "error in read_next_timestep\n");
00279 return 1;
00280 }
00281 }
00282 close_file_read(v);
00283 }
00284 return 0;
00285 }
00286
00287
00288 #endif
00289