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