00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "molfile_plugin.h"
00019
00020 #include <stdio.h>
00021 #include <string.h>
00022 #include <stdlib.h>
00023
00024 #define PSF_RECORD_LENGTH 160
00025
00026 typedef struct {
00027 FILE *fp;
00028 int numatoms;
00029 int charmmfmt;
00030 int charmmcmap;
00031 int charmmcheq;
00032 int charmmext;
00033 int nbonds;
00034 int *from, *to;
00035 } psfdata;
00036
00037
00038
00039
00040
00041
00042 static int get_psf_atom(FILE *f, char *name, char *atype, char *resname,
00043 char *segname, int *resid, float *q, float *m, int charmmext) {
00044 char inbuf[PSF_RECORD_LENGTH+2];
00045 int i,num;
00046
00047 if (inbuf != fgets(inbuf, PSF_RECORD_LENGTH+1, f)) {
00048 return(-1);
00049 }
00050
00051 if (strlen(inbuf) < 50) {
00052 fprintf(stderr, "Line too short in psf file: \n%s\n", inbuf);
00053 return -1;
00054 }
00055
00056 num = atoi(inbuf);
00057
00058 if (charmmext == 1) {
00059 strncpy(segname, inbuf+11, 7);
00060 segname[7] = '\0';
00061 strncpy(resname, inbuf+29, 7);
00062 resname[7] = '\0';
00063 strncpy(name, inbuf+38, 7);
00064 name[7] = '\0';
00065 strncpy(atype, inbuf+46, 7);
00066 atype[7] = '\0';
00067
00068
00069 for (i=7; i >= 0; i--) {
00070 if (segname[i] == ' ')
00071 segname[i] = '\0';
00072 if (resname[i] == ' ')
00073 resname[i] = '\0';
00074 if (name[i] == ' ')
00075 name[i] = '\0';
00076 if (atype[i] == ' ')
00077 atype[i] = '\0';
00078 }
00079
00080 *resid = atoi(inbuf+20);
00081 *q = (float) atof(inbuf+52);
00082 *m = (float) atof(inbuf+68);
00083 } else {
00084 strncpy(segname, inbuf+9, 4);
00085 segname[4] = '\0';
00086 strncpy(resname, inbuf+19, 4);
00087 resname[4] = '\0';
00088 strncpy(name, inbuf+24, 4);
00089 name[4] = '\0';
00090 strncpy(atype, inbuf+29, 4);
00091 atype[4] = '\0';
00092
00093
00094 for (i=3; i >= 0; i--) {
00095 if (segname[i] == ' ')
00096 segname[i] = '\0';
00097 if (resname[i] == ' ')
00098 resname[i] = '\0';
00099 if (name[i] == ' ')
00100 name[i] = '\0';
00101 if (atype[i] == ' ')
00102 atype[i] = '\0';
00103 }
00104
00105 *resid = atoi(inbuf+13);
00106 *q = (float) atof(inbuf+34);
00107 *m = (float) atof(inbuf+50);
00108 }
00109
00110 #if 0
00111
00112
00113 if (psf->charmmcheq) {
00114
00115 }
00116 #endif
00117
00118 return num;
00119 }
00120
00121
00122
00123 static int start_psf_bonds(FILE *f) {
00124 char inbuf[PSF_RECORD_LENGTH+2];
00125 int nbond = -1;
00126
00127
00128 do {
00129 if (inbuf != fgets(inbuf, PSF_RECORD_LENGTH+1, f)) {
00130
00131 return (-1);
00132 }
00133 if (strlen(inbuf) > 0 && strstr(inbuf,"NBOND"))
00134 nbond = atoi(inbuf);
00135 } while (nbond == -1);
00136
00137 return nbond;
00138 }
00139
00140
00141
00142
00143
00144 static int get_psf_bonds(FILE *f, int nbond, int fromAtom[], int toAtom[], int charmmext) {
00145 char *bondptr=NULL;
00146 char inbuf[PSF_RECORD_LENGTH+2];
00147 int i=0;
00148 size_t minlinesize;
00149
00150 while (i < nbond) {
00151 if ((i % 4) == 0) {
00152
00153 if (!fgets(inbuf, PSF_RECORD_LENGTH+2, f)) {
00154
00155 break;
00156 }
00157
00158 if (nbond-i >= 4) {
00159 if(charmmext == 1) minlinesize = 20*4 ; else minlinesize = 16*4;
00160 } else {
00161 if(charmmext == 1) minlinesize = 20*(nbond-i); else minlinesize = 16*(nbond-i);
00162 }
00163 if (strlen(inbuf) < minlinesize) {
00164 fprintf(stderr, "Bonds line too short in psf file: \n%s\n", inbuf);
00165 break;
00166 }
00167 bondptr = inbuf;
00168 }
00169 if ((fromAtom[i] = atoi(bondptr)) < 1)
00170 break;
00171 if(charmmext == 1) bondptr += 10; else bondptr += 8;
00172 if ((toAtom[i] = atoi(bondptr)) < 1)
00173 break;
00174 if(charmmext == 1) bondptr += 10; else bondptr += 8;
00175 i++;
00176 }
00177
00178 return (i == nbond);
00179 }
00180
00181
00182
00183
00184
00185 static void *open_psf_read(const char *path, const char *filetype,
00186 int *natoms) {
00187 FILE *fp;
00188 char inbuf[PSF_RECORD_LENGTH*8+2];
00189 psfdata *psf;
00190
00191
00192
00193
00194
00195 if (!path)
00196 return NULL;
00197
00198 if ((fp = fopen(path, "r")) == NULL) {
00199 fprintf(stderr, "Couldn't open psf file %s\n", path);
00200 return NULL;
00201 }
00202
00203 *natoms = MOLFILE_NUMATOMS_NONE;
00204
00205 psf = (psfdata *) malloc(sizeof(psfdata));
00206 memset(psf, 0, sizeof(psfdata));
00207 psf->fp = fp;
00208 psf->charmmfmt = 0;
00209 psf->charmmext = 0;
00210
00211
00212 do {
00213
00214 if (inbuf != fgets(inbuf, PSF_RECORD_LENGTH*8+1, fp)) {
00215
00216 *natoms = MOLFILE_NUMATOMS_NONE;
00217 fclose(fp);
00218 free(psf);
00219 return NULL;
00220 }
00221
00222 if (strlen(inbuf) > 0) {
00223 if (!strstr(inbuf, "REMARKS")) {
00224 if (strstr(inbuf, "PSF")) {
00225 if (strstr(inbuf, "EXT")) {
00226 psf->charmmfmt = 1;
00227 psf->charmmext = 1;
00228 }
00229 if (strstr(inbuf, "CHEQ")) {
00230 psf->charmmfmt = 1;
00231 psf->charmmcheq = 1;
00232 }
00233 if (strstr(inbuf, "CMAP")) {
00234 psf->charmmfmt = 1;
00235 psf->charmmcmap = 1;
00236 }
00237 } else if (strstr(inbuf, "NATOM")) {
00238 *natoms = atoi(inbuf);
00239 }
00240 }
00241 }
00242 } while (*natoms == MOLFILE_NUMATOMS_NONE);
00243
00244 if (psf->charmmcheq || psf->charmmcmap) {
00245 printf("psfplugin) Detected a Charmm31 PSF file\n");
00246 }
00247 if (psf->charmmext) {
00248 printf("psfplugin) Detected a Charmm31 PSF EXTEnded file\n");
00249 }
00250
00251 psf->numatoms = *natoms;
00252
00253 return psf;
00254 }
00255
00256 static int read_psf(void *v, int *optflags, molfile_atom_t *atoms) {
00257 psfdata *psf = (psfdata *)v;
00258 int i;
00259
00260
00261 *optflags = MOLFILE_MASS | MOLFILE_CHARGE;
00262
00263 for (i=0; i<psf->numatoms; i++) {
00264 molfile_atom_t *atom = atoms+i;
00265 if (get_psf_atom(psf->fp, atom->name, atom->type,
00266 atom->resname, atom->segid,
00267 &atom->resid, &atom->charge, &atom->mass, psf->charmmext) < 0) {
00268 fprintf(stderr, "couldn't read atom %d\n", i);
00269 fclose(psf->fp);
00270 psf->fp = NULL;
00271 return MOLFILE_ERROR;
00272 }
00273 atom->chain[0] = atom->segid[0];
00274 atom->chain[1] = '\0';
00275 }
00276
00277 return MOLFILE_SUCCESS;
00278 }
00279
00280 static int read_bonds(void *v, int *nbonds, int **fromptr, int **toptr, float **bondorder) {
00281 psfdata *psf = (psfdata *)v;
00282
00283
00284 *nbonds = start_psf_bonds(psf->fp);
00285
00286 if (*nbonds > 0) {
00287 psf->from = (int *) malloc(*nbonds*sizeof(int));
00288 psf->to = (int *) malloc(*nbonds*sizeof(int));
00289
00290 if (!get_psf_bonds(psf->fp, *nbonds, psf->from, psf->to, psf->charmmext)) {
00291 fclose(psf->fp);
00292 psf->fp = NULL;
00293 return MOLFILE_ERROR;
00294 }
00295 *fromptr = psf->from;
00296 *toptr = psf->to;
00297 *bondorder = NULL;
00298 } else {
00299 printf("psfplugin) WARNING: no bonds defined in PSF file.\n");
00300 }
00301
00302 return MOLFILE_SUCCESS;
00303 }
00304
00305
00306 static void close_psf_read(void *mydata) {
00307 psfdata *psf = (psfdata *)mydata;
00308 if (psf) {
00309 if (psf->fp != NULL)
00310 fclose(psf->fp);
00311 if (psf->from != NULL)
00312 free(psf->from);
00313 if (psf->to != NULL)
00314 free(psf->to);
00315 free(psf);
00316 }
00317 }
00318
00319
00320 static void *open_psf_write(const char *path, const char *filetype,
00321 int natoms) {
00322 FILE *fp;
00323 psfdata *psf;
00324
00325 fp = fopen(path, "w");
00326 if (!fp) {
00327 fprintf(stderr, "Unable to open file %s for writing\n", path);
00328 return NULL;
00329 }
00330 psf = (psfdata *) malloc(sizeof(psfdata));
00331 psf->fp = fp;
00332 psf->numatoms = natoms;
00333 psf->charmmfmt = 0;
00334 psf->nbonds = 0;
00335 psf->to = NULL;
00336 psf->from = NULL;
00337
00338 return psf;
00339 }
00340
00341 static int write_psf_structure(void *v, int optflags,
00342 const molfile_atom_t *atoms) {
00343 psfdata *psf = (psfdata *)v;
00344 const molfile_atom_t *atom;
00345 int i;
00346
00347 printf("psfplugin) WARNING: PSF file is incomplete, no angles, dihedrals,\n");
00348 printf("psfplugin) or impropers will be written. \n");
00349
00350 fprintf(psf->fp, "PSF\n\n%8d !NTITLE\n", 1);
00351
00352 if (psf->charmmfmt) {
00353 fprintf(psf->fp," REMARKS %s\n","VMD generated structure charmm psf file");
00354
00355 printf("psfplugin) WARNING: Charmm format PSF file is incomplete, atom type ID\n");
00356 printf("psfplugin) codes have been emitted as '0'. \n");
00357 } else {
00358 fprintf(psf->fp," REMARKS %s\n","VMD generated structure x-plor psf file");
00359 }
00360 fprintf(psf->fp, "\n");
00361
00362
00363 fprintf(psf->fp, "%8d !NATOM\n", psf->numatoms);
00364
00365
00366 for (i=0; i<psf->numatoms; i++) {
00367 const char *atomname;
00368 atom = &atoms[i];
00369 atomname = atom->name;
00370
00371
00372 while (*atomname == ' ')
00373 atomname++;
00374
00375 if (psf->charmmfmt) {
00376
00377 fprintf(psf->fp, "%8d %-4s %-4d %-4s %-4s %4d %10.6f %9.4f %10d\n",
00378 i+1, atom->segid, atom->resid, atom->resname,
00379 atomname, 0, atom->charge, atom->mass, 0);
00380 } else {
00381 fprintf(psf->fp, "%8d %-4s %-4d %-4s %-4s %-4s %10.6f %9.4f %10d\n",
00382 i+1, atom->segid, atom->resid, atom->resname,
00383 atomname, atom->type, atom->charge, atom->mass, 0);
00384 }
00385 }
00386 fprintf(psf->fp, "\n");
00387
00388
00389 if (psf->nbonds > 0 && psf->from != NULL && psf->to != NULL) {
00390 fprintf(psf->fp, "%8d !NBOND: bonds\n", psf->nbonds);
00391 for (i=0; i<psf->nbonds; i++) {
00392 fprintf(psf->fp, "%8d%8d", psf->from[i], psf->to[i]);
00393 if ((i % 4) == 3)
00394 fprintf(psf->fp, "\n");
00395 }
00396 if ((i % 4) != 0)
00397 fprintf(psf->fp, "\n");
00398 fprintf(psf->fp, "\n");
00399 } else {
00400 fprintf(psf->fp, "%8d !NBOND: bonds\n", 0);
00401 fprintf(psf->fp, "\n\n");
00402 }
00403
00404 fprintf(psf->fp, "%8d !NTHETA: angles\n", 0);
00405
00406 fprintf(psf->fp, "\n\n");
00407
00408 fprintf(psf->fp, "%8d !NPHI: dihedrals\n", 0);
00409
00410 fprintf(psf->fp, "\n\n");
00411
00412 fprintf(psf->fp, "%8d !NIMPHI: impropers\n", 0);
00413
00414 fprintf(psf->fp, "\n\n");
00415
00416 fprintf(psf->fp, "%8d !NDON: donors\n", 0);
00417 fprintf(psf->fp, "\n\n");
00418
00419 fprintf(psf->fp, "%8d !NACC: acceptors\n", 0);
00420 fprintf(psf->fp, "\n\n");
00421
00422 fprintf(psf->fp, "%8d !NNB\n\n", 0);
00423
00424 {
00425 int i, fullrows;
00426 fullrows = psf->numatoms/8;
00427 for (i=0; i<fullrows; ++i)
00428 fprintf(psf->fp, "%8d%8d%8d%8d%8d%8d%8d%8d\n", 0, 0, 0, 0, 0, 0, 0, 0);
00429 for (i=psf->numatoms - fullrows*8; i; --i)
00430 fprintf(psf->fp, "%8d", 0);
00431 }
00432 fprintf(psf->fp, "\n\n");
00433
00434 fprintf(psf->fp, "%8d %7d !NGRP\n%8d%8d%8d\n", 1, 0, 0, 0, 0);
00435 fprintf(psf->fp, "\n");
00436
00437 return MOLFILE_SUCCESS;
00438 }
00439
00440 static int write_bonds(void *v, int nbonds, int *fromptr, int *toptr, float *bondorderptr) {
00441 psfdata *psf = (psfdata *)v;
00442 int i;
00443
00444
00445 psf->nbonds = nbonds;
00446 psf->from = (int *) malloc(nbonds * sizeof(int));
00447 memcpy(psf->from, fromptr, nbonds * sizeof(int));
00448 psf->to = (int *) malloc(nbonds * sizeof(int));
00449 memcpy(psf->to, toptr, nbonds * sizeof(int));
00450
00451 return MOLFILE_SUCCESS;
00452 }
00453
00454 static void close_psf_write(void *v) {
00455 psfdata *psf = (psfdata *)v;
00456 fclose(psf->fp);
00457
00458
00459 if (psf->from != NULL)
00460 free(psf->from);
00461 if (psf->to != NULL)
00462 free(psf->to);
00463 free(psf);
00464 }
00465
00466
00467
00468
00469
00470
00471 static molfile_plugin_t plugin = {
00472 vmdplugin_ABIVERSION,
00473 MOLFILE_PLUGIN_TYPE,
00474 "psf",
00475 "CHARMM,NAMD,XPLOR PSF",
00476 "Justin Gullingsrud, John Stone",
00477 0,
00478 7,
00479 VMDPLUGIN_THREADSAFE,
00480 "psf",
00481 open_psf_read,
00482 read_psf,
00483 read_bonds,
00484 0,
00485 close_psf_read,
00486 open_psf_write,
00487 write_psf_structure,
00488 0,
00489 close_psf_write,
00490 0,
00491 0,
00492 0,
00493 0,
00494 write_bonds
00495 };
00496
00497 VMDPLUGIN_API int VMDPLUGIN_init() {
00498 return VMDPLUGIN_SUCCESS;
00499 }
00500
00501 VMDPLUGIN_API int VMDPLUGIN_register(void *v, vmdplugin_register_cb cb) {
00502 (*cb)(v, (vmdplugin_t *)&plugin);
00503 return VMDPLUGIN_SUCCESS;
00504 }
00505
00506 VMDPLUGIN_API int VMDPLUGIN_fini() {
00507 return VMDPLUGIN_SUCCESS;
00508 }