4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
27 * Green Red Orange Magenta Azure Cyan Skyblue
29 static char *SRCID_pdbio_c
= "$Id$";
43 static char *pdbtp
[epdbNR
]={
44 "ATOM ","HETATM", "ANISOU", "CRYST1",
45 "COMPND", "ENDMDL", "TER", "HEADER", "TITLE", "REMARK"
48 static char *pdbformat
="%6s%5u %-4.4s%3.3s %c%4d %8.3f%8.3f%8.3f%6.2f%6.2f\n";
49 static char *pdbformat4
="%6s%5u %-4.4s %3.3s %c%4d %8.3f%8.3f%8.3f%6.2f%6.2f\n";
50 static bool bTER
=FALSE
;
51 #define REMARK_SIM_BOX "REMARK THIS IS A SIMULATION BOX"
54 void pdb_use_ter(bool bSet
)
59 static void gromacs_name(char *name
)
65 if (isdigit(name
[0])) {
67 for(i
=1; i
<length
; i
++)
71 if(strcmp(name
,"OXT")==0)
75 void write_pdbfile_indexed(FILE *out
,char *title
,
76 t_atoms
*atoms
,rvec x
[],matrix box
,char chain
,
78 atom_id nindex
, atom_id index
[])
80 char resnm
[6],nm
[6],ch
,*pdbform
;
85 fprintf(out
,"HEADER %s\n",(title
&& title
[0])?title
:bromacs());
87 fprintf(out
,"REMARK THIS IS A SIMULATION BOX\n");
88 fprintf(out
,"CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f P 1 1\n",
89 10*box
[XX
][XX
],10*box
[YY
][YY
],10*box
[ZZ
][ZZ
],90.0,90.0,90.0);
91 for (ii
=0; ii
<nindex
; ii
++) {
93 resnr
=atoms
->atom
[i
].resnr
;
94 strcpy(resnm
,*atoms
->resname
[resnr
]);
95 strcpy(nm
,*atoms
->atomname
[i
]);
98 resnr
= resnr
% 10000;
102 if (atoms
->atom
[i
].chain
)
103 ch
=atoms
->atom
[i
].chain
;
106 if (atoms
->pdbinfo
) {
107 type
=atoms
->pdbinfo
[i
].type
;
108 occup
=atoms
->pdbinfo
[i
].occup
;
109 bfac
=atoms
->pdbinfo
[i
].bfac
;
122 fprintf(out
,pdbform
,pdbtp
[type
],(i
+1)%100000,nm
,resnm
,ch
,resnr
,
123 10*x
[i
][XX
],10*x
[i
][YY
],10*x
[i
][ZZ
],occup
,bfac
);
126 fprintf(out
,"TER\n");
127 if (bEndmodel
&& !bTER
)
128 fprintf(out
,"ENDMDL\n");
131 void write_pdbfile(FILE *out
,char *title
,
132 t_atoms
*atoms
,rvec x
[],matrix box
,char chain
,
137 snew(index
,atoms
->nr
);
138 for(i
=0; i
<atoms
->nr
; i
++)
140 write_pdbfile_indexed(out
,title
,atoms
,x
,box
,chain
,bEndmodel
,
145 void hwrite_pdb_conf_indexed(FILE *out
,char *title
,
146 t_atoms
*atoms
,rvec x
[],matrix box
,
147 atom_id nindex
,atom_id index
[])
149 write_pdbfile_indexed(out
,title
,atoms
,x
,box
,0,TRUE
,nindex
,index
);
152 void write_pdb_confs(char *outfile
,t_atoms
**atoms
,rvec
*x
[],int number
)
156 char chain
,str
[STRLEN
];
158 out
=ffopen(outfile
,"w");
160 for(n
=0;(n
<number
);n
++) {
162 fprintf(stderr
,"writing chain %c\n",chain
);
163 sprintf(str
,"Chain %c",chain
);
164 write_pdbfile(out
,str
,atoms
[n
],x
[n
],NULL
,chain
,(n
==number
-1));
170 int line2type(char *line
)
179 for(k
=0; (k
<epdbNR
); k
++)
180 if (strncmp(type
,pdbtp
[k
],strlen(pdbtp
[k
])) == 0)
186 static void read_anisou(char line
[],int natom
,t_atoms
*atoms
)
190 char anr
[12],anm
[12];
194 for(k
=0; (k
<5); k
++,j
++) anr
[k
]=line
[j
];
197 for(k
=0; (k
<4); k
++,j
++) anm
[k
]=line
[j
];
201 /* Strip off spaces */
204 /* Search backwards for number and name only */
206 for(i
=natom
-1; (i
>=0); i
--)
207 if ((strcmp(anm
,*(atoms
->atomname
[i
])) == 0) &&
208 (atomnr
== atoms
->pdbinfo
[i
].atomnr
))
211 fprintf(stderr
,"Skipping ANISOU record (atom %s %d not found)\n",
214 if (sscanf(line
+29,"%d%d%d%d%d%d",
215 &atoms
->pdbinfo
[i
].uij
[U11
],&atoms
->pdbinfo
[i
].uij
[U22
],
216 &atoms
->pdbinfo
[i
].uij
[U33
],&atoms
->pdbinfo
[i
].uij
[U12
],
217 &atoms
->pdbinfo
[i
].uij
[U13
],&atoms
->pdbinfo
[i
].uij
[U23
])
219 atoms
->pdbinfo
[i
].bAnisotropic
= TRUE
;
222 fprintf(stderr
,"Invalid ANISOU record for atom %d\n",i
);
223 atoms
->pdbinfo
[i
].bAnisotropic
= FALSE
;
228 static int read_atom(t_symtab
*symtab
,char line
[],int type
,int natom
,
229 t_atoms
*atoms
,rvec x
[],bool bChange
)
234 char anr
[12],anm
[12],altloc
,resnm
[12],chain
[12],resnr
[12];
235 char xc
[12],yc
[12],zc
[12],occup
[12],bfac
[12],pdbresnr
[12];
236 static char oldresnm
[12],oldresnr
[12];
239 if (natom
>=atoms
->nr
)
240 fatal_error(0,"\nFound more atoms (%d) in pdb file than expected (%d)",
245 for(k
=0; (k
<5); k
++,j
++) anr
[k
]=line
[j
];
249 for(k
=0; (k
<4); k
++,j
++) anm
[k
]=line
[j
];
254 for(k
=0; (k
<4); k
++,j
++)
259 for(k
=0; (k
<1); k
++,j
++)
263 for(k
=0; (k
<4); k
++,j
++) {
274 /* X,Y,Z Coordinate */
275 for(k
=0; (k
<8); k
++,j
++) xc
[k
]=line
[j
];
277 for(k
=0; (k
<8); k
++,j
++) yc
[k
]=line
[j
];
279 for(k
=0; (k
<8); k
++,j
++) zc
[k
]=line
[j
];
283 for(k
=0; (k
<6); k
++,j
++) occup
[k
]=line
[j
];
287 for(k
=0; (k
<6); k
++,j
++) bfac
[k
]=line
[j
];
290 atomn
=&(atoms
->atom
[natom
]);
291 if ((natom
==0) || (strcmp(oldresnr
,pdbresnr
)!=0) ||
292 (strcmp(oldresnm
,resnm
)!=0)) {
293 strcpy(oldresnr
,pdbresnr
);
294 strcpy(oldresnm
,resnm
);
298 newres
=atoms
->atom
[natom
-1].resnr
+1;
299 atoms
->nres
=newres
+1;
300 atoms
->resname
[newres
]=put_symtab(symtab
,resnm
);
303 newres
=atoms
->atom
[natom
-1].resnr
;
306 atoms
->atomname
[natom
]=put_symtab(symtab
,anm
);
307 atomn
->chain
=chain
[0];
309 x
[natom
][XX
]=atof(xc
)*0.1;
310 x
[natom
][YY
]=atof(yc
)*0.1;
311 x
[natom
][ZZ
]=atof(zc
)*0.1;
312 if (atoms
->pdbinfo
) {
313 atoms
->pdbinfo
[natom
].type
=type
;
314 atoms
->pdbinfo
[natom
].atomnr
=atoi(anr
);
315 atoms
->pdbinfo
[natom
].altloc
=altloc
;
316 strcpy(atoms
->pdbinfo
[natom
].pdbresnr
,pdbresnr
);
317 atoms
->pdbinfo
[natom
].bfac
=atof(bfac
);
318 atoms
->pdbinfo
[natom
].occup
=atof(occup
);
327 bool is_hydrogen(char *nm
)
336 else if ((isdigit(buf
[0])) && (buf
[1] == 'H'))
341 bool is_dummymass(char *nm
)
348 if ((buf
[0] == 'M') && isdigit(buf
[strlen(buf
)-1]))
354 int read_pdbfile(FILE *in
,char *title
,
355 t_atoms
*atoms
,rvec x
[],matrix box
,bool bChange
)
357 static t_symtab symtab
;
358 static bool bFirst
=TRUE
;
361 char xc
[12],yc
[12],zc
[12];
372 open_symtab(&symtab
);
379 while (!bStop
&& (fgets2(line
,STRLEN
,in
) != NULL
)) {
380 line_type
= line2type(line
);
385 natom
= read_atom(&symtab
,line
,line_type
,natom
,atoms
,x
,bChange
);
389 if (atoms
->pdbinfo
!= NULL
)
390 read_anisou(line
,natom
,atoms
);
395 sscanf(line
,"%*s%s%s%s%lf%lf%lf",xc
,yc
,zc
,&xa
,&ya
,&za
);
396 if (xa
==90 || ya
==90 || za
==90) {
397 box
[XX
][XX
] = atof(xc
)*0.1;
398 box
[YY
][YY
] = atof(yc
)*0.1;
399 box
[ZZ
][ZZ
] = atof(zc
)*0.1;
408 /* skip HEADER or TITLE and spaces */
409 while (c
&& (c
[0]!=' ')) c
++;
410 while (c
&& (c
[0]==' ')) c
++;
411 /* truncate after title */
421 if ((!strstr(line
,": ")) || (strstr(line
+6,"MOLECULE:"))) {
422 if ( !(c
=strstr(line
+6,"MOLECULE:")) )
424 /* skip 'MOLECULE:' and spaces */
425 while (c
&& (c
[0]!=' ')) c
++;
426 while (c
&& (c
[0]==' ')) c
++;
427 /* truncate after title */
430 while ( (d
[-1]==';') && d
>c
) d
--;
459 void get_pdb_coordnum(FILE *in
,int *natoms
)
464 while (fgets2(line
,STRLEN
,in
)) {
465 if ( ( bTER
&& (strncmp(line
,"TER",3) == 0)) ||
466 (!bTER
&& (strncmp(line
,"ENDMDL",6) == 0)) )
468 if ((strncmp(line
,"ATOM ",6) == 0) || (strncmp(line
,"HETATM",6) == 0))
473 void read_pdb_conf(char *infile
,char *title
,
474 t_atoms
*atoms
,rvec x
[],matrix box
,bool bChange
)
478 in
= ffopen(infile
,"r");
479 read_pdbfile(in
,title
,atoms
,x
,box
,bChange
);