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 * GRowing Old MAkes el Chrono Sweat
29 static char *SRCID_editconf_c
= "$Id$";
67 static char *pdbtp
[epdbNR
]={"ATOM ","HETATM"};
68 static char *pdbformat
=
69 "%6s%5d %-4.4s%3.3s %c%4d %8.3f%8.3f%8.3f%6.2f%6.2f\n";
71 real
calc_mass(t_atoms
*atoms
,bool bGetMass
)
77 for(i
=0; (i
<atoms
->nr
); i
++) {
79 atoms
->atom
[i
].m
= get_mass(*atoms
->resname
[atoms
->atom
[i
].resnr
],
81 tmass
+= atoms
->atom
[i
].m
;
87 void calc_geom(char *indexfn
, t_atoms
*atoms
,
88 rvec
*x
, rvec geom_center
, rvec min
, rvec max
)
96 /* Make an index for principal component analysis */
97 fprintf(stderr
,"\nSelect group for selecting system size:\n");
98 get_index(atoms
,indexfn
,1,&isize
,&index
,&grpnames
);
103 for(i
=0; (i
<isize
); i
++) {
107 clear_rvec(geom_center
);
108 for (j
=0; (j
<DIM
); j
++)
109 min
[j
]=max
[j
]=x
[0][j
];
110 for (i
=0; (i
<isize
); i
++) {
112 rvec_inc(geom_center
,x
[ii
]);
113 for (j
=0; (j
<DIM
); j
++) {
114 if (x
[ii
][j
] < min
[j
]) min
[j
]=x
[ii
][j
];
115 if (x
[ii
][j
] > max
[j
]) max
[j
]=x
[ii
][j
];
118 svmul(1.0/isize
,geom_center
,geom_center
);
122 void center_conf(int natom
, rvec
*x
, rvec center
, rvec geom_cent
)
127 rvec_sub(center
,geom_cent
,shift
);
129 printf("shift : %6.3f %6.3f %6.3f\n",
130 shift
[XX
],shift
[YY
],shift
[ZZ
]);
132 for (i
=0; (i
<natom
); i
++)
133 rvec_inc(x
[i
], shift
);
136 void scale_conf(int natom
,rvec x
[],matrix box
,rvec scale
)
140 for(i
=0; (i
<natom
); i
++) {
141 for (j
=0; (j
<DIM
); j
++)
144 for (j
=0; (j
<DIM
); j
++)
145 box
[j
][j
] *= scale
[j
];
148 void rm_gropbc(t_atoms
*atoms
,rvec x
[],matrix box
)
153 /* check periodic boundary */
154 for(d
=0;(d
<DIM
);d
++) {
155 for(n
=1;(n
<atoms
->nr
);n
++) {
156 dist
= x
[n
][d
]-x
[n
-1][d
];
157 if ( fabs(dist
) > 0.9 * box
[d
][d
] ) {
167 void read_bfac(char *fn
, int *n_bfac
, double **bfac_val
, int **bfac_nr
)
172 *n_bfac
= get_lines(fn
, &bfac_lines
);
173 snew(*bfac_val
, *n_bfac
);
174 snew(*bfac_nr
, *n_bfac
);
175 fprintf(stderr
, "Reading %d B-factors from %s\n",*n_bfac
,fn
);
176 for(i
=0; (i
<*n_bfac
); i
++) {
177 /*fprintf(stderr, "Line %d: %s",i,bfac_lines[i]);*/
178 sscanf(bfac_lines
[i
],"%d %lf",&(*bfac_nr
)[i
],&(*bfac_val
)[i
]);
179 /*fprintf(stderr," nr %d val %g\n",(*bfac_nr)[i],(*bfac_val)[i]);*/
184 void set_pdb_conf_bfac(int natoms
,int nres
,t_atoms
*atoms
,rvec x
[],
185 matrix box
,int n_bfac
,double *bfac
,int *bfac_nr
,
186 bool peratom
, bool bLegend
)
189 real bfac_min
,bfac_max
;
196 for(i
=0; (i
<n_bfac
); i
++) {
197 if (bfac_nr
[i
]-1>=atoms
->nres
)
199 if ((bfac_nr
[i
]-1<0) || (bfac_nr
[i
]-1>=atoms
->nr
))
200 fatal_error(0,"Index of B-Factor %d is out of range: %d (%g)",
201 i
+1,bfac_nr
[i
],bfac
[i
]);
202 if (bfac
[i
] > bfac_max
)
204 if (bfac
[i
] < bfac_min
)
207 while ( (bfac_max
> 99.99) || (bfac_min
< -99.99) ) {
208 fprintf(stderr
,"Range of values for B-factors too large (min %g, max %g) "
209 "will scale down a factor 10\n",bfac_min
,bfac_max
);
210 for(i
=0; (i
<n_bfac
); i
++)
215 while ( (abs(bfac_max
) < 0.5) && (abs(bfac_min
) < 0.5) ) {
216 fprintf(stderr
,"Range of values for B-factors too small (min %g, max %g) "
217 "will scale up a factor 10\n",bfac_min
,bfac_max
);
218 for(i
=0; (i
<n_bfac
); i
++)
224 for(i
=0; (i
<natoms
); i
++)
225 atoms
->pdbinfo
[i
].bfac
=0;
228 fprintf(stderr
,"Will attach %d B-factors to %d residues\n",
230 for(i
=0; (i
<n_bfac
); i
++) {
232 for(n
=0; (n
<natoms
); n
++)
233 if ( bfac_nr
[i
] == (atoms
->atom
[n
].resnr
+1) ) {
234 atoms
->pdbinfo
[n
].bfac
=bfac
[i
];
238 sprintf(buf
,"Residue nr %d not found\n",bfac_nr
[i
]);
243 fprintf(stderr
,"Will attach %d B-factors to %d atoms\n",n_bfac
,natoms
);
244 for(i
=0; (i
<n_bfac
); i
++) {
245 atoms
->pdbinfo
[bfac_nr
[i
]-1].bfac
=bfac
[i
];
250 void pdb_legend(FILE *out
,int natoms
,int nres
,t_atoms
*atoms
,rvec x
[])
252 real bfac_min
,bfac_max
,xmin
,ymin
,zmin
;
261 for (i
=0; (i
<natoms
); i
++) {
262 xmin
= min(xmin
,x
[i
][XX
]);
263 ymin
= min(ymin
,x
[i
][YY
]);
264 zmin
= min(zmin
,x
[i
][ZZ
]);
265 bfac_min
= min(bfac_min
,atoms
->pdbinfo
[i
].bfac
);
266 bfac_max
= max(bfac_max
,atoms
->pdbinfo
[i
].bfac
);
268 fprintf(stderr
,"B-factors range from %g to %g\n",bfac_min
,bfac_max
);
269 sprintf(buf
,"%s","LEG");
271 for (i
=1; (i
<12); i
++) {
272 fprintf(out
,pdbformat
,
273 "ATOM ",natoms
+1+i
,"CA",buf
,' ',nres
+1,
274 (xmin
+(i
*0.12))*10,ymin
*10,zmin
*10,1.0,
275 bfac_min
+ ((i
-1.0)*(bfac_max
-bfac_min
)/10) );
279 int main(int argc
, char *argv
[])
281 static char *desc
[] = {
282 "editconf converts generic structure format to [TT].gro[tt] or",
283 "[TT].pdb[tt].[PAR]",
284 "A number of options is present to modify the coordinates",
285 "and box. [TT]-d[tt], [TT]-dc[tt] and [TT]-box[tt] modify the box and",
286 "center the coordinates relative to the new box.",
287 "[TT]-dc[tt] takes precedent over [TT]-d[tt]. [TT]-box[tt]",
288 "takes precedent over [TT]-dc[tt] and [TT]-d[tt].[PAR]",
289 "[TT]-rotate[tt] rotates the coordinates and velocities.",
290 "[TT]-princ[tt] aligns the principal axes of the system along the",
291 "coordinate axes, this may allow you to decrease the box volume,",
292 "but beware that molecules can rotate significantly in a nanosecond.[PAR]",
293 "Scaling is applied before any of the other operations are",
294 "performed. Boxes can be scaled to give a certain density (option",
295 "[TT]-density[tt]). A special feature of the scaling option, when the",
296 "factor -1 is given in one dimension, one obtains a mirror image,",
297 "mirrored in one of the plains, when one uses -1 in three dimensions",
298 "a point-mirror image is obtained.[PAR]",
299 "Groups are selected after all operations have been applied.[PAR]",
300 "Periodicity can be removed in a crude manner.",
301 "It is important that the box sizes at the bottom of your input file",
302 "are correct when the periodicity is to be removed.[PAR]",
303 "The program can optionally rotate the solute molecule to align the",
304 "molecule along its principal axes ([TT]-rotate[tt])[PAR]",
305 "When writing [TT].pdb[tt] files, B-factors can be",
306 "added with the [TT]-bf[tt] option. B-factors are read",
307 "from a file with with following format: first line states number of",
308 "entries in the file, next lines state an index",
309 "followed by a B-factor. The B-factors will be attached per residue",
310 "unless an index is larger than the number of residues or unless the",
311 "[TT]-atom[tt] option is set. Obviously, any type of numeric data can",
312 "be added instead of B-factors. [TT]-legend[tt] will produce",
313 "a row of CA atoms with B-factors ranging from the minimum to the",
314 "maximum value found, effectively making a legend for viewing.[PAR]",
315 "Finally with option [TT]-label[tt] editconf can add a chain identifier",
316 "to a pdb file, which can be useful for analysis with e.g. rasmol."
318 static char *bugs
[] = {
319 "For complex molecules, the periodicity removal routine may break down, "
320 "in that case you can use trjconv"
322 static real dist
= 0.0,rbox
=0.0;
323 static bool bNDEF
=FALSE
,bRMPBC
=FALSE
,bCenter
=FALSE
;
324 static bool peratom
=FALSE
,bLegend
=FALSE
,bOrient
=FALSE
;
325 static rvec scale
={1.0,1.0,1.0},newbox
={0.0,0.0,0.0};
326 static real rho
=1000.0;
327 static rvec center
={0.0,0.0,0.0},rotangles
={0.0,0.0,0.0};
328 static char *label
="A";
330 { "-ndef", FALSE
, etBOOL
, {&bNDEF
},
331 "Choose output from default index groups" },
332 { "-d", FALSE
, etREAL
, {&dist
},
333 "Distance between the solute and the rectangular box" },
334 { "-dc", FALSE
, etREAL
, {&dist
},
335 "Distance between the solute and the cubic box" },
336 { "-box", FALSE
, etRVEC
, {&newbox
}, "Size of box" },
337 { "-c", FALSE
, etBOOL
, {&bCenter
},
338 "Center molecule in box (implied by -d -dc -box)" },
339 { "-center", FALSE
, etRVEC
, {¢er
}, "Coordinates of geometrical center"},
340 { "-rotate", FALSE
, etRVEC
, {rotangles
},
341 "Rotation around the X, Y and Z axes in degrees" },
342 { "-princ", FALSE
, etBOOL
, {&bOrient
}, "Orient molecule(s) along their principal axes" },
343 { "-scale", FALSE
, etRVEC
, {&scale
}, "Scaling factor" },
344 { "-density",FALSE
, etREAL
, {&rho
},
345 "Density (g/l) of the output box achieved by scaling" },
346 { "-pbc", FALSE
, etBOOL
, {&bRMPBC
},
347 "Remove the periodicity (make molecule whole again)" },
348 { "-atom", FALSE
, etBOOL
, {&peratom
}, "Force B-factor attachment per atom" },
349 { "-legend", FALSE
, etBOOL
, {&bLegend
}, "Make B-factor legend" },
350 { "-label", FALSE
, etSTR
, {&label
}, "Add chain label for all residues" }
352 #define NPA asize(pa)
355 char *infile
,*outfile
,title
[STRLEN
];
356 int outftp
,natom
,i
,j
,n_bfac
;
363 rvec
*x
,*v
,gc
,min
,max
,size
;
365 bool bSetSize
,bCubic
,bDist
,bSetCenter
;
366 bool bHaveV
,bScale
,bRho
,bRotate
,bCalcGeom
;
367 real xs
,ys
,zs
,xcent
,ycent
,zcent
,d
;
369 { efSTX
, "-f", NULL
, ffREAD
},
370 { efNDX
, "-n", NULL
, ffOPTRD
},
371 { efSTO
, NULL
, NULL
, ffWRITE
},
372 { efDAT
, "-bf", "bfact", ffOPTRD
}
374 #define NFILE asize(fnm)
376 CopyRight(stderr
,argv
[0]);
377 parse_common_args(&argc
,argv
,0,FALSE
,NFILE
,fnm
,NPA
,pa
,
378 asize(desc
),desc
,asize(bugs
),bugs
);
380 bSetSize
= opt2parg_bSet("-box" ,NPA
,pa
);
381 bSetCenter
= opt2parg_bSet("-center" ,NPA
,pa
);
382 bCubic
= opt2parg_bSet("-dc",NPA
,pa
);
383 bDist
= opt2parg_bSet("-d" ,NPA
,pa
) || bCubic
;
384 bCenter
= bCenter
|| bDist
|| bSetCenter
|| bSetSize
;
385 bScale
= opt2parg_bSet("-scale" ,NPA
,pa
);
386 bRho
= opt2parg_bSet("-density",NPA
,pa
);
387 bRotate
= opt2parg_bSet("-rotate",NPA
,pa
);
389 fprintf(stderr
,"WARNING: setting -density overrides -scale");
390 bScale
= bScale
|| bRho
;
391 bCalcGeom
= bCenter
|| bRotate
|| bOrient
|| bScale
;
393 infile
= ftp2fn(efSTX
,NFILE
,fnm
);
394 outfile
= ftp2fn(efSTO
,NFILE
,fnm
);
395 outftp
= fn2ftp(outfile
);
397 get_stx_coordnum(infile
,&natom
);
398 init_t_atoms(&atoms
,natom
,TRUE
);
401 read_stx_conf(infile
,title
,&atoms
,x
,v
,box
);
402 printf("Read %d atoms\n",atoms
.nr
);
405 for (i
=0; (i
<natom
) && !bHaveV
; i
++)
406 for (j
=0; (j
<DIM
) && !bHaveV
; j
++)
407 bHaveV
=bHaveV
|| (v
[i
][j
]!=0);
408 printf("%selocities found\n",bHaveV
?"V":"No v");
412 rm_gropbc(&atoms
,x
,box
);
415 calc_geom(ftp2fn_null(efNDX
,NFILE
,fnm
),&atoms
,x
, gc
, min
, max
);
416 rvec_sub(max
, min
, size
);
417 printf("size : %6.3f %6.3f %6.3f\n", size
[XX
], size
[YY
], size
[ZZ
]);
418 printf("center : %6.3f %6.3f %6.3f\n", gc
[XX
], gc
[YY
], gc
[ZZ
]);
419 printf("box : %6.3f %6.3f %6.3f (%.3f nm^3)\n",
420 box
[XX
][XX
], box
[YY
][YY
], box
[ZZ
][ZZ
], det(box
));
424 /* Orient the principal axes along the coordinate axes */
425 orient_mol(&atoms
,ftp2fn_null(efNDX
,NFILE
,fnm
),x
,bHaveV
? v
: NULL
);
428 /* scale coordinates and box */
430 /* Compute scaling constant */
434 mass
= calc_mass(&atoms
,!fn2bTPX(infile
));
435 dens
= (mass
*AMU
)/(vol
*NANO
*NANO
*NANO
);
436 fprintf(stderr
,"Volume of input %g (nm3)\n",vol
);
437 fprintf(stderr
,"Mass of input %g (a.m.u.)\n",mass
);
438 fprintf(stderr
,"Density of input %g (g/l)\n",dens
);
440 fatal_error(0,"Cannot scale density with zero box\n");
442 fatal_error(0,"Cannot scale density with zero mass\n");
444 scale
[XX
] = scale
[YY
] = scale
[ZZ
] = pow(dens
/rho
,1.0/3.0);
445 fprintf(stderr
,"Scaling all box edges by %g\n",scale
[XX
]);
447 scale_conf(atoms
.nr
,x
,box
,scale
);
452 printf("Rotating %g, %g, %g degrees around the X, Y and Z axis respectively\n",rotangles
[XX
],rotangles
[YY
],rotangles
[ZZ
]);
454 rotangles
[i
] *= DEG2RAD
;
455 rotate_conf(natom
,x
,v
,rotangles
[XX
],rotangles
[YY
],rotangles
[ZZ
]);
459 /* recalc geometrical center and max and min coordinates and size */
460 calc_geom(ftp2fn_null(efNDX
,NFILE
,fnm
),&atoms
,x
, gc
, min
, max
);
461 rvec_sub(max
, min
, size
);
462 if (bScale
|| bOrient
|| bRotate
)
463 printf("new size : %6.3f %6.3f %6.3f\n",size
[XX
],size
[YY
],size
[ZZ
]);
466 /* calculate new boxsize */
468 for (i
=0; (i
<DIM
); i
++)
469 box
[i
][i
]=size
[i
]+2*dist
;
471 for (i
=0; (i
<DIM
); i
++)
475 for (i
=1; (i
<DIM
); i
++)
476 if (box
[i
][i
]>d
) d
=box
[i
][i
];
477 for (i
=0; (i
<DIM
); i
++)
480 /* calculate new coords for geometrical center */
482 for (i
=0; (i
<DIM
); i
++)
483 center
[i
]=box
[i
][i
]/2;
485 /* center molecule on 'center' */
487 center_conf(natom
,x
,center
,gc
);
490 if (bCenter
|| bScale
|| bOrient
|| bRotate
) {
491 calc_geom(NULL
,&atoms
,x
, gc
, min
, max
);
492 printf("new center: %6.3f %6.3f %6.3f\n",
493 gc
[XX
],gc
[YY
],gc
[ZZ
]);
495 if ( bOrient
|| bScale
|| bDist
|| bSetSize
)
496 printf("new box : %6.3f %6.3f %6.3f (%.3f nm^3)\n",
497 box
[XX
][XX
], box
[YY
][YY
], box
[ZZ
][ZZ
], det(box
));
499 if (opt2bSet("-n",NFILE
,fnm
) || bNDEF
) {
500 fprintf(stderr
,"\nSelect a group for output:\n");
501 get_index(&atoms
,opt2fn_null("-n",NFILE
,fnm
),
502 1,&isize
,&index
,&groupnames
);
503 if (opt2bSet("-bf",NFILE
,fnm
))
504 fatal_error(0,"combination not implemented: -bf -n or -bf -ndef");
506 write_sto_conf_indexed(outfile
,title
,&atoms
,x
,bHaveV
?v
:NULL
,box
,
510 if (outftp
!= efPDB
) {
511 write_sto_conf(outfile
,title
,&atoms
,x
,bHaveV
?v
:NULL
,box
);
513 out
=ffopen(outfile
,"w");
514 if (opt2bSet("-bf",NFILE
,fnm
)) {
515 read_bfac(opt2fn("-bf",NFILE
,fnm
),&n_bfac
,&bfac
,&bfac_nr
);
516 set_pdb_conf_bfac(atoms
.nr
,atoms
.nres
,&atoms
,x
,box
,
517 n_bfac
,bfac
,bfac_nr
,peratom
,bLegend
);
519 if (opt2parg_bSet("-label",NPA
,pa
)) {
520 for(i
=0; (i
<atoms
.nr
); i
++)
521 atoms
.atom
[i
].chain
=label
[0];
523 write_pdbfile(out
,title
,&atoms
,x
,box
,0,!bLegend
);
525 pdb_legend(out
,atoms
.nr
,atoms
.nres
,&atoms
,x
);