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
00209 VMDPLUGIN_API int VMDPLUGIN_init() {
00210 memset(&plugin, 0, sizeof(molfile_plugin_t));
00211 plugin.abiversion = vmdplugin_ABIVERSION;
00212 plugin.type = MOLFILE_PLUGIN_TYPE;
00213 plugin.name = "namdbin";
00214 plugin.prettyname = "NAMD Binary Coordinates";
00215 plugin.author = "James Phillips, Justin Gullingsrud";
00216 plugin.majorv = 0;
00217 plugin.minorv = 2;
00218 plugin.is_reentrant = VMDPLUGIN_THREADSAFE;
00219 plugin.filename_extension = "coor";
00220 plugin.open_file_read = open_namdbin_read;
00221 plugin.read_next_timestep = read_next_timestep;
00222 plugin.close_file_read = close_file_read;
00223 plugin.open_file_write = open_namdbin_write;
00224 plugin.write_timestep = write_timestep;
00225 plugin.close_file_write = close_file_write;
00226 return VMDPLUGIN_SUCCESS;
00227 }
00228
00229 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00230 (*cb)(v, (vmdplugin_t *)&plugin);
00231 return VMDPLUGIN_SUCCESS;
00232 }
00233
00234 VMDPLUGIN_API int VMDPLUGIN_fini() {
00235 return VMDPLUGIN_SUCCESS;
00236 }
00237
00238
00239 #ifdef TEST_NAMDBINPLUGIN
00240
00241 int main(int argc, char *argv[]) {
00242 molfile_header_t header;
00243 molfile_timestep_t timestep;
00244 void *v;
00245 int i;
00246
00247 while (--argc) {
00248 ++argv;
00249 v = open_namdbin_read(*argv, &header);
00250 if (!v) {
00251 fprintf(stderr, "open_namdbin_read failed for file %s\n", *argv);
00252 return 1;
00253 }
00254 timestep.coords = (float *)malloc(3*sizeof(float)*header.numatoms);
00255 for (i=0; i<header.numsteps; i++) {
00256 int rc = read_next_timestep(v, ×tep);
00257 if (rc) {
00258 fprintf(stderr, "error in read_next_timestep\n");
00259 return 1;
00260 }
00261 }
00262 close_file_read(v);
00263 }
00264 return 0;
00265 }
00266
00267
00268 #endif
00269