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 * Great Red Oystrich Makes All Chemists Sane
29 static char *SRCID_trjconv_c
= "$Id$";
57 static void center_x(rvec x
[],matrix box
,int n
,atom_id index
[])
63 copy_rvec(x
[index
[0]],cmin
);
64 copy_rvec(x
[index
[0]],cmax
);
65 for(i
=0; (i
<n
); i
++) {
67 for(m
=0; (m
<DIM
); m
++) {
68 if (x
[ai
][m
] < cmin
[m
])
70 else if (x
[ai
][m
] > cmax
[m
])
74 for(m
=0; (m
<DIM
); m
++) {
75 dx
[m
]=-(box
[m
][m
]-(cmin
[m
]+cmax
[m
]))*0.5;
77 for(i
=0; (i
<n
); i
++) {
84 void check_trn(char *fn
)
86 if ((fn2ftp(fn
) != efTRJ
) && (fn2ftp(fn
) != efTRR
))
87 fatal_error(0,"%s is not a trj file, exiting\n",fn
);
91 void do_trunc(char *fn
, real t0
)
103 fatal_error(0,"You forgot to set the truncation time");
105 /* Check whether this is a .trj file */
108 in
= open_trn(fn
,"r");
111 fprintf(stderr
,"Sorry, can not trunc %s, truncation of this filetype is not supported\n",fn
);
115 fpos
= fio_ftell(in
);
117 while (!bStop
&& fread_trnheader(in
,&sh
,&bOK
)) {
118 fread_htrn(in
,&sh
,NULL
,NULL
,NULL
,NULL
);
122 fseek(fp
,fpos
,SEEK_SET
);
127 fprintf(stderr
,"Do you REALLY want to truncate this trajectory (%s) at:\n"
128 "frame %d, time %g, bytes %ld ??? (type YES if so)\n",
131 if (strcmp(yesno
,"YES") == 0) {
132 fprintf(stderr
,"Once again, I'm gonna DO this...\n");
137 fprintf(stderr
,"Ok, I'll forget about it\n");
141 fprintf(stderr
,"Already at end of file (t=%g)...\n",t
);
148 bool bRmod(double a
,double b
)
153 iq
= ((1.0+tol
)*a
)/b
;
155 if (fabs(a
-b
*iq
) <= tol
*a
)
161 int main(int argc
,char *argv
[])
163 static char *desc
[] = {
164 "trjconv can convert trajectory files in many ways:[BR]",
165 "[BB]1.[bb] from one format to another[BR]",
166 "[BB]2.[bb] select a subset of atoms[BR]",
167 "[BB]3.[bb] remove periodicity from molecules[BR]",
168 "[BB]4.[bb] keep multimeric molecules together[BR]",
169 "[BB]5.[bb] center atoms in the box[BR]",
170 "[BB]6.[bb] fit atoms to reference structure[BR]",
171 "[BB]7.[bb] remove duplicate frames[BR]",
172 "[BB]8.[bb] reduce the number of frames[BR]",
173 "[BB]9.[bb] change the timestamps of the frames (e.g. t0 and delta-t)",
175 "The program [TT]trjcat[tt] can concatenate multiple trajectory files.",
177 "Currently seven formats are supported for input and output:",
178 "[TT].xtc[tt], [TT].trr[tt], [TT].trj[tt], [TT].gro[tt], [TT].g96[tt],",
179 "[TT].pdb[tt] and [TT].g87[tt].",
180 "The file formats are detected from the file extension.",
181 "For [TT].gro[tt] and [TT].xtc[tt] files the output precision ",
182 "can be given as a number of ",
183 "decimal places. Note that velocities are only supported in ",
184 "[TT].trr[tt], [TT].trj[tt], [TT].gro[tt] and [TT].g96[tt] files.[PAR]",
185 "The option [TT]-app[tt] can be used to",
186 "append output to an existing trajectory file.",
187 "No checks are performed to ensure integrity",
188 "of the resulting combined trajectory file.",
189 "[TT].pdb[tt] files with all frames concatenated can be viewed with",
190 "[TT]rasmol -nmrpdb[tt].[PAR]",
191 "It is possible to select part of your trajectory and write it out",
192 "to a new trajectory file in order to save disk space, e.g. for leaving",
193 "out the water from a trajectory of a protein in water.",
194 "[BB]ALWAYS[bb] put the original trajectory on tape!",
195 "We recommend to use the portable [TT].xtc[tt] format for your analysis",
196 "to save disk space and to have portable files.[PAR]",
197 "There are two options for fitting the trajectory to a reference",
198 "either for essential dynamics analysis or for whatever.",
199 "The first option is just plain fitting to a reference structure",
200 "in the structure file, the second option is a progressive fit",
201 "in which the first timeframe is fitted to the reference structure ",
202 "in the structure file to obtain and each subsequent timeframe is ",
203 "fitted to the previously fitted structure. This way a continuous",
204 "trajectory is generated, which might not be the case when using the",
205 "regular fit method, e.g. when your protein undergoes large",
206 "conformational transitions.[PAR]",
207 "The option [TT]-pbc[tt] sets the type of periodic boundary condition",
208 "treatment. [TT]whole[tt] makes broken molecules whole (a run input",
209 "file is required). [TT]-pbc[tt] is changed form [TT]none[tt] to",
210 "[TT]whole[tt] when [TT]-fit[tt] or [TT]-pfit[tt] is set.",
211 "[TT]inbox[tt] puts all the atoms in the box.",
212 "[TT]nojump[tt] checks if atoms jump across the box and then puts",
213 "them back. This has the effect that all molecules",
214 "will remain whole (provided they were whole in the initial",
215 "conformation), note that this ensures a continuous trajectory but",
216 "molecules may diffuse out of the box. The starting configuration",
217 "for this procedure is taken from the structure file, if one is",
218 "supplied, otherwise it is the first frame.",
219 "Use [TT]-center[tt] to put the system in the center of the box.",
220 "This is especially useful for multimeric proteins, since this",
221 "procedure will ensure the subunits stay together in the trajectory",
222 "(due to PBC, they might be separated), providing they were together",
223 "in the initial conformation.[PAR]",
224 "With the option [TT]-dt[tt] it is possible to reduce the number of ",
225 "frames in the output. This option relies on the accuracy of the times",
226 "in your input trajectory, so if these are inaccurate use the",
228 "option to modify the time (this can be done simultaneously).[PAR]",
229 "Using [TT]-trunc[tt] trjconv can truncate [TT].trj[tt] in place, i.e.",
230 "without copying the file. This is useful when a run has crashed",
231 "during disk I/O (one more disk full), or when two contiguous",
232 "trajectories must be concatenated without have double frames.[PAR]",
233 "Also the option [TT]-checkdouble[tt] may be used to remove all",
234 "duplicate frames from such a concatenated trajectory, this is done",
235 "by ignoring all frames with a time smaller than or equal to the previous",
236 "frame. [TT]trjcat[tt] is more suitable for concatenating trajectory",
238 "The option [TT]-dump[tt] can be used to extract a frame at or near",
239 "one specific time from your trajectory."
242 static char *pbc_opt
[] = { NULL
, "none", "whole", "inbox", "nojump", NULL
};
244 static bool bAppend
=FALSE
,bSeparate
=FALSE
,bVels
=TRUE
;
245 static bool bCenter
=FALSE
,bFit
=FALSE
,bPFit
=FALSE
,bBox
=TRUE
;
246 static bool bCheckDouble
=FALSE
;
247 static int skip_nr
=1,prec
=3;
248 static real tzero
=0.0,delta_t
=0.0,timestep
=0.0,ttrunc
=-1,tdump
=-1;
249 static rvec newbox
= {0,0,0}, shift
= {0,0,0};
250 static char *exec_command
=NULL
;
253 { "-pbc", FALSE
, etENUM
, {pbc_opt
},
255 { "-center", FALSE
, etBOOL
, {&bCenter
},
256 "Center atoms in box" },
257 { "-box", FALSE
, etRVEC
, {&newbox
},
258 "Size for new cubic box (default: read from input)" },
259 { "-shift", FALSE
, etRVEC
, {&shift
},
260 "All coordinates will be shifted by framenr*shift" },
261 { "-fit", FALSE
, etBOOL
, {&bFit
},
262 "Fit molecule to ref structure in the structure file" },
263 { "-pfit", FALSE
, etBOOL
, {&bPFit
},
264 "Progressive fit, to the previous fitted structure" },
265 { "-prec", FALSE
, etINT
, {&prec
},
266 "Precision for .xtc and .gro writing in number of decimal places" },
267 { "-vel", FALSE
, etBOOL
, {&bVels
},
268 "Read and write velocities if possible" },
269 { "-skip", FALSE
, etINT
, {&skip_nr
},
270 "Only write every nr-th frame" },
271 { "-dt", FALSE
, etREAL
, {&delta_t
},
272 "Only write frame when t MOD dt = first time" },
273 { "-t0", FALSE
, etREAL
, {&tzero
},
274 "Starting time for trajectory"
275 "(default: don't change)"},
277 { "-trunc", FALSE
, etREAL
, {&ttrunc
},
278 "Truncate input trj file after this amount of ps" },
280 { "-dump", FALSE
, etREAL
, {&tdump
},
281 "Dump frame nearest specified time" },
282 { "-g87box", FALSE
, etBOOL
, {&bBox
},
283 "Write a box for .g87" },
284 { "-exec", FALSE
, etSTR
, {&exec_command
},
285 "Execute command for every output frame with the frame number "
287 { "-timestep", FALSE
, etREAL
, {×tep
},
288 "Change time step between frames" },
289 { "-app", FALSE
, etBOOL
, {&bAppend
},
291 { "-sep", FALSE
, etBOOL
, {&bSeparate
},
292 "Write each frame to a separate .gro or .pdb file"},
293 { "-checkdouble", FALSE
, etBOOL
, {&bCheckDouble
},
294 "Only write frames with time larger than previous frame" }
299 int status
,ftp
,ftpin
,file_nr
;
300 rvec
*x
,*xn
,*xout
,*v
,*vn
,*vout
;
302 real xtcpr
, lambda
,*w_rls
=NULL
;
304 int m
,i
,d
,frame
,outframe
,natoms
=0,nout
,nre
,step
;
307 t_atoms
*atoms
=NULL
,useatoms
;
311 atom_id
*ind_fit
,*ind_rms
;
312 char *gn_fit
,*gn_rms
;
313 real t
,pt
,tshift
=0,t0
=-1,dt
=0.001;
314 bool bPBC
,bInBox
,bNoJump
;
315 bool bCopy
,bDoIt
,bIndex
,bTDump
,bSetTime
,bTPS
=FALSE
,bDTset
=FALSE
;
316 bool bExec
,bTimeStep
=FALSE
,bDumpFrame
=FALSE
,bToldYouOnce
=FALSE
;
317 bool bHaveNextFrame
,bHaveX
=FALSE
,bHaveV
=FALSE
,bSetBox
;
319 char *top_file
,*in_file
,*out_file
,out_file2
[256],*charpt
;
320 char top_title
[256],title
[256],command
[256],filemode
[5];
324 { efTRX
, "-f", NULL
, ffREAD
},
325 { efTRX
, "-o", "trajout", ffWRITE
},
326 { efTPS
, NULL
, NULL
, ffOPTRD
},
327 { efNDX
, NULL
, NULL
, ffOPTRD
}
329 #define NFILE asize(fnm)
331 CopyRight(stderr
,argv
[0]);
332 parse_common_args(&argc
,argv
,PCA_CAN_TIME
,TRUE
,
333 NFILE
,fnm
,asize(pa
),pa
,asize(desc
),desc
,
336 top_file
=ftp2fn(efTPS
,NFILE
,fnm
);
338 /* Check command line */
339 in_file
=opt2fn("-f",NFILE
,fnm
);
342 do_trunc(in_file
,ttrunc
);
348 bSetBox
= opt2parg_bSet("-box", asize(pa
), pa
);
349 bSetTime
= opt2parg_bSet("-t0", asize(pa
), pa
);
350 bExec
= opt2parg_bSet("-exec", asize(pa
), pa
);
351 bTimeStep
= opt2parg_bSet("-timestep", asize(pa
), pa
);
352 bTDump
= opt2parg_bSet("-dump", asize(pa
), pa
);
353 bPBC
= (strcmp(pbc_opt
[0],"whole") == 0);
354 bInBox
= (strcmp(pbc_opt
[0],"inbox") == 0);
355 bNoJump
= (strcmp(pbc_opt
[0],"nojump") == 0);
356 if (bFit
&& (strcmp(pbc_opt
[0],"none") == 0))
359 /* prec is in nr of decimal places, xtcprec is a multiplication factor: */
361 for (i
=0; i
<prec
; i
++)
364 bIndex
=ftp2bSet(efNDX
,NFILE
,fnm
);
366 /* Determine output type */
367 out_file
=opt2fn("-o",NFILE
,fnm
);
368 ftp
=fn2ftp(out_file
);
369 fprintf(stderr
,"Will write %s: %s\n",ftp2ext(ftp
),ftp2desc(ftp
));
371 /* check if velocities are possible in input and output files */
372 ftpin
=fn2ftp(in_file
);
373 bVels
= ((ftp
==efTRR
) ||(ftp
==efTRJ
) || (ftp
==efGRO
))
374 && ((ftpin
==efTRR
) ||(ftpin
==efTRJ
) || (ftpin
==efGRO
));
383 fprintf(stderr
,"The number of frames to skip is <= 0. "
384 "Writing out all frames.\n\n");
388 /* Determine whether to read a topology */
389 bTPS
= (ftp2bSet(efTPS
,NFILE
,fnm
) ||
390 bPBC
|| bFit
|| (ftp
== efGRO
) || (ftp
== efPDB
));
392 /* Determine if when can read index groups */
393 bIndex
= (bIndex
|| bTPS
);
396 read_tps_conf(top_file
,top_title
,&top
,&xp
,NULL
,box
,bFit
);
398 /* top_title is only used for gro and pdb,
399 * the header in such a file is top_title t= ...
400 * to prevent a double t=, remove it from top_title
402 if ((charpt
=strstr(top_title
," t= ")))
407 printf("Select group for root least squares fit\n");
408 get_index(atoms
,ftp2fn_null(efNDX
,NFILE
,fnm
),
409 1,&ifit
,&ind_fit
,&gn_fit
);
412 fatal_error(0,"Need at least 3 points to fit!\n");
416 printf("Select group for output\n");
417 get_index(atoms
,ftp2fn_null(efNDX
,NFILE
,fnm
),
418 1,&nout
,&index
,&grpnm
);
421 /* no index file, so read natoms from TRX */
422 natoms
=read_first_x(&status
,in_file
,&t
,&x
,box
);
425 for(i
=0;i
<natoms
;i
++)
430 /* if xp was not snew-ed before, do it now */
435 snew(w_rls
,atoms
->nr
);
436 for(i
=0; (i
<ifit
); i
++)
437 w_rls
[ind_fit
[i
]]=atoms
->atom
[ind_fit
[i
]].m
;
439 /* Restore reference structure and set to origin,
440 store original location (to put structure back) */
441 rm_pbc(&(top
.idef
),atoms
->nr
,box
,xp
,xp
);
442 copy_rvec(xp
[index
[0]],x_shift
);
443 reset_x(ifit
,ind_fit
,nout
,index
,xp
,w_rls
);
444 rvec_dec(x_shift
,xp
[index
[0]]);
447 /* Make atoms struct for output in GRO or PDB files */
448 if ((ftp
== efGRO
) || ((ftp
== efG96
) && bTPS
) || (ftp
== efPDB
)) {
449 /* get memory for stuff to go in pdb file */
450 init_t_atoms(&useatoms
,atoms
->nr
,FALSE
);
451 sfree(useatoms
.resname
);
452 useatoms
.resname
=atoms
->resname
;
453 for(i
=0;(i
<nout
);i
++) {
454 useatoms
.atomname
[i
]=atoms
->atomname
[index
[i
]];
455 useatoms
.atom
[i
].resnr
=atoms
->atom
[index
[i
]].resnr
;
456 useatoms
.nres
=max(useatoms
.nres
,useatoms
.atom
[i
].resnr
+1);
460 /* open trj file for reading */
462 natoms
=read_first_x_or_v(&status
,in_file
,&t
,&x
,&v
,box
);
464 natoms
=read_first_x (&status
,in_file
,&t
,&x
, box
);
471 fatal_error(0,"No atoms found in file %s",in_file
);
473 /* open output for writing */
474 if ((bAppend
) && (fexist(out_file
))) {
475 strcpy(filemode
,"a");
476 fprintf(stderr
,"APPENDING to existing file %s\n",out_file
);
478 strcpy(filemode
,"w");
481 xdr
= open_xtc(out_file
,filemode
);
484 out
=ffopen(out_file
,filemode
);
489 trjout
= open_tpx(out_file
,filemode
);
495 out
=ffopen(out_file
,filemode
);
501 /* check if index is meaningful */
502 for(i
=0; i
<nout
; i
++) {
503 if (index
[i
] >= natoms
)
504 fatal_error(0,"Element %d of index group %s is %d, this is larger than the number of atoms in the trajectory file (%d)",i
,grpnm
,index
[i
]+1,natoms
);
505 bCopy
= bCopy
|| (i
!= index
[i
]);
519 fprintf(out
,"Generated by %s. #atoms=%d, %s BOX is stored in "
520 "this file.\n",Program(),nout
,bBox
? "a" : "NO");
522 /* Start the big loop over frames */
530 /* generate new box */
533 for (m
=0; m
<DIM
; m
++)
534 box
[m
][m
] = newbox
[m
];
538 /* determine timestep */
547 bDumpFrame
= (t
>= tdump
-(0.5*dt
) ) && (t
<= tdump
+(0.5*dt
) );
550 /* determine if an atom jumped across the box and reset it if so */
551 if (bNoJump
&& (bTPS
|| frame
!=0)) {
552 for(i
=0; (i
<natoms
); i
++)
553 for(d
=0; (d
<DIM
); d
++)
554 if ( x
[i
][d
]-xp
[i
][d
] > 0.5*box
[d
][d
] )
555 x
[i
][d
] -= box
[d
][d
];
556 else if ( x
[i
][d
]-xp
[i
][d
] < -0.5*box
[d
][d
] )
557 x
[i
][d
] += box
[d
][d
];
561 /* Now modify the coords according to the flags,
562 for normal fit, this is only done for output frames */
563 rm_pbc(&(top
.idef
),natoms
,box
,x
,x
);
565 reset_x(ifit
,ind_fit
,nout
,index
,x
,w_rls
);
566 do_fit(natoms
,w_rls
,xp
,x
);
569 /* store this set of coordinates for future use */
570 if (bPFit
|| bNoJump
) {
571 for(i
=0; (i
<natoms
); i
++) {
572 copy_rvec(x
[i
],xp
[i
]);
573 rvec_inc(x
[i
],x_shift
);
577 if ( bCheckDouble
&& (t
<=pt
) && !bToldYouOnce
) {
578 fprintf(stderr
,"\nRemoving duplicate frame(s) after t=%g "
579 "(t=%g, frame %d)\n",pt
,t
,frame
);
583 if ( ( ( !bTDump
&& (frame
% skip_nr
== 0) ) || bDumpFrame
) &&
584 ( !bCheckDouble
|| ( bCheckDouble
&& (t
> pt
) ) ) ) {
586 /* remember time from this frame */
591 t
=tzero
+frame
*timestep
;
597 fprintf(stderr
,"\nDumping frame at t= %g\n",t
);
599 /* check for writing at each delta_t */
600 bDoIt
=(delta_t
== 0);
602 bDoIt
=bRmod(t
-tzero
, delta_t
);
604 if (bDoIt
|| bTDump
) {
605 /* print sometimes */
608 fprintf(stderr
,"\nContinue writing frames from t=%g, frame=%d\n",
611 if ( ((outframe
% SKIP
) == 0) || (outframe
< SKIP
) )
612 fprintf(stderr
," -> frame %6d time %8.3f \r",outframe
,t
);
615 /* Now modify the coords according to the flags,
616 for PFit we did this already! */
618 rm_pbc(&(top
.idef
),natoms
,box
,x
,x
);
621 reset_x(ifit
,ind_fit
,nout
,index
,x
,w_rls
);
622 do_fit(natoms
,w_rls
,xp
,x
);
623 for(i
=0; (i
<natoms
); i
++)
624 rvec_inc(x
[i
],x_shift
);
629 center_x(x
,box
,nout
,index
);
633 for(i
=0; (i
<nout
); i
++) {
634 copy_rvec(x
[index
[i
]],xout
[i
]);
635 if (bVels
) copy_rvec(v
[index
[i
]],vout
[i
]);
639 /* this should make sure all atoms in output are really inside
640 a rectangular box. Was needed to make movies.
641 Peter Tieleman, Mon Jul 15 1996
644 put_atoms_in_box(nout
,box
,xout
);
646 if (opt2parg_bSet("-shift",asize(pa
),pa
))
647 for(i
=0; (i
<nout
); i
++)
648 for (d
=0; (d
<DIM
); d
++)
649 xout
[i
][d
] += outframe
*shift
[d
];
652 /* check if we have velocities and/or coordinates,
653 don't ask me why you can have a frame w/o coords !? */
656 for (i
=0; (i
<natoms
); i
++)
657 for (d
=0; (d
<DIM
); d
++) {
658 bHaveV
=bHaveV
|| v
[i
][d
];
659 bHaveX
=bHaveX
|| x
[i
][d
];
666 fwrite_trn(trjout
,frame
,t
,0,box
,
668 bHaveX
? xout
: NULL
,
669 bHaveV
? vout
: NULL
,
674 write_gms(out
,nout
,xout
,bBox
? box
: NULL
);
677 write_xtc(xdr
,nout
,frame
,t
,box
,xout
,xtcpr
);
682 sprintf(title
,"Generated by trjconv : %s t= %9.5f",top_title
,t
);
684 sprintf(out_file2
,"%d_%s",file_nr
,out_file
);
685 out
=ffopen(out_file2
,"w");
689 write_hconf_p(out
,title
,&useatoms
,prec
,xout
,bHaveV
?vout
:NULL
,box
);
692 fprintf(out
,"REMARK GENERATED BY TRJCONV\n");
693 sprintf(title
,"%s t= %9.5f",top_title
,t
);
694 write_pdbfile(out
,title
,&useatoms
,xout
,box
,0,TRUE
);
697 if (bSeparate
|| bTDump
)
698 write_g96_conf(out
,title
,&useatoms
,xout
,bHaveV
?vout
:NULL
,box
,
702 fprintf(out
,"TITLE\n%s\nEND\n",title
);
703 fprintf(out
,"TIMESTEP\n%9d%15.9f\nEND\nPOSITIONRED\n",
705 for(i
=0; i
<nout
; i
++)
706 fprintf(out
,"%15.9f%15.9f%15.9f\n",
707 xout
[i
][XX
],xout
[i
][YY
],xout
[i
][ZZ
]);
708 fprintf(out
,"END\nBOX\n%15.9f%15.9f%15.9f\nEND\n",
709 box
[XX
][XX
],box
[YY
][YY
],box
[ZZ
][ZZ
]);
720 fatal_error(0,"DHE, ftp=%d\n",ftp
);
723 /* execute command */
726 sprintf(c
,"%s %d",exec_command
,file_nr
-1);
727 /*fprintf(stderr,"Executing '%s'\n",c);*/
735 bHaveNextFrame
=read_next_x_or_v(status
,&t
,natoms
,x
,v
,box
);
737 bHaveNextFrame
=read_next_x (status
,&t
,natoms
,x
, box
);
738 } while (!bDumpFrame
&& bHaveNextFrame
);
740 if ( bTDump
&& !bDumpFrame
)
741 fprintf(stderr
,"\nWARNING no frame found near specified time (%g), "
742 "trajectory ended at %g\n",tdump
,t
);
743 fprintf(stderr
,"\n");
749 else if (out
!= NULL
)