Don't use POSIX fnmatch() for pattern matching.
[gromacs/qmmm-gamess-us.git] / src / tools / gmx_trjcat.c
blob3c1f30916c75a9017e6f023a27c2015d4f955caa
1 /*
2 *
3 * This source code is part of
4 *
5 * G R O M A C S
6 *
7 * GROningen MAchine for Chemical Simulations
8 *
9 * VERSION 3.2.0
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
32 * And Hey:
33 * Green Red Orange Magenta Azure Cyan Skyblue
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
39 #include <string.h>
40 #include <math.h>
41 #include "macros.h"
42 #include "sysstuff.h"
43 #include "smalloc.h"
44 #include "typedefs.h"
45 #include "copyrite.h"
46 #include "gmxfio.h"
47 #include "tpxio.h"
48 #include "trnio.h"
49 #include "statutil.h"
50 #include "futil.h"
51 #include "pdbio.h"
52 #include "confio.h"
53 #include "names.h"
54 #include "index.h"
55 #include "vec.h"
56 #include "xtcio.h"
57 #include "do_fit.h"
58 #include "rmpbc.h"
59 #include "wgms.h"
60 #include "magic.h"
61 #include "pbc.h"
62 #include "xvgr.h"
63 #include "xdrf.h"
65 #define TIME_EXPLICIT 0
66 #define TIME_CONTINUE 1
67 #define TIME_LAST 2
68 #ifndef FLT_MAX
69 #define FLT_MAX 1e36
70 #endif
71 #define FLAGS (TRX_READ_X | TRX_READ_V | TRX_READ_F)
73 static void scan_trj_files(char **fnms, int nfiles, real *readtime,
74 real *timestep, atom_id imax,
75 const output_env_t oenv)
77 /* Check start time of all files */
78 int i, status, natoms = 0;
79 real t;
80 t_trxframe fr;
81 bool ok;
83 for (i = 0; i < nfiles; i++)
85 ok = read_first_frame(oenv, &status, fnms[i], &fr, FLAGS);
87 if (!ok)
88 gmx_fatal(FARGS,"\nCouldn't read frame from file." );
89 if(fr.bTime)
90 readtime[i]=fr.time;
91 else
93 readtime[i]=0;
94 fprintf(stderr,"\nWARNING: Couldn't find a time in the frame.\n");
97 if(i==0)
99 natoms=fr.natoms;
101 else
103 if (imax==NO_ATID)
105 if(natoms!=fr.natoms)
106 gmx_fatal(FARGS,"\nDifferent numbers of atoms (%d/%d) in files",
107 natoms,fr.natoms);
109 else
111 if(fr.natoms <= imax)
113 gmx_fatal(FARGS,"\nNot enough atoms (%d) for index group (%d)",
114 fr.natoms,imax);
118 ok=read_next_frame(oenv,status,&fr);
119 if(ok && fr.bTime)
121 timestep[i] = fr.time - readtime[i];
123 else
125 timestep[i] = 0;
128 close_trj(status);
130 fprintf(stderr,"\n");
132 sfree(fr.x);
135 static void sort_files(char **fnms, real *settime, int nfile)
137 int i, j, minidx;
138 real timeswap;
139 char *chptr;
141 for (i = 0; i < nfile; i++)
143 minidx = i;
144 for (j = i + 1; j < nfile; j++)
146 if (settime[j] < settime[minidx])
148 minidx = j;
151 if (minidx != i)
153 timeswap = settime[i];
154 settime[i] = settime[minidx];
155 settime[minidx] = timeswap;
156 chptr = fnms[i];
157 fnms[i] = fnms[minidx];
158 fnms[minidx] = chptr;
163 static void edit_files(char **fnms, int nfiles, real *readtime, real *timestep,
164 real *settime, int *cont_type, bool bSetTime,
165 bool bSort, const output_env_t oenv)
167 int i;
168 bool ok;
169 char inputstring[STRLEN], *chptr;
171 if (bSetTime)
173 fprintf(stderr, "\n\nEnter the new start time (%s) for each file.\n"
174 "There are two special options, both disable sorting:\n\n"
175 "c (continue) - The start time is taken from the end\n"
176 "of the previous file. Use it when your continuation run\n"
177 "restarts with t=0.\n\n"
178 "l (last) - The time in this file will be changed the\n"
179 "same amount as in the previous. Use it when the time in the\n"
180 "new run continues from the end of the previous one,\n"
181 "since this takes possible overlap into account.\n\n",
182 get_time_unit(oenv));
184 fprintf(
185 stderr,
186 " File Current start (%s) New start (%s)\n"
187 "---------------------------------------------------------\n",
188 get_time_unit(oenv), get_time_unit(oenv));
190 for (i = 0; i < nfiles; i++)
192 fprintf(stderr, "%25s %10.3f %s ", fnms[i],
193 conv_time(oenv, readtime[i]), get_time_unit(oenv));
194 ok = FALSE;
197 if (NULL == fgets(inputstring, STRLEN - 1, stdin))
199 gmx_fatal(FARGS,"Error reading user input" );
202 inputstring[strlen(inputstring)-1]=0;
204 if(inputstring[0]=='c' || inputstring[0]=='C')
206 cont_type[i]=TIME_CONTINUE;
207 bSort=FALSE;
208 ok=TRUE;
209 settime[i]=FLT_MAX;
211 else if(inputstring[0]=='l' ||
212 inputstring[0]=='L')
214 cont_type[i]=TIME_LAST;
215 bSort=FALSE;
216 ok=TRUE;
217 settime[i]=FLT_MAX;
219 else
221 settime[i]=strtod(inputstring,&chptr)*
222 get_time_invfactor(oenv);
223 if(chptr==inputstring)
225 fprintf(stderr,"'%s' not recognized as a floating point number, 'c' or 'l'. "
226 "Try again: ",inputstring);
228 else {
229 cont_type[i]=TIME_EXPLICIT;
230 ok=TRUE;
233 } while (!ok);
235 if(cont_type[0]!=TIME_EXPLICIT)
237 cont_type[0]=TIME_EXPLICIT;
238 settime[0]=0;
241 else
243 for(i=0;i<nfiles;i++)
245 settime[i]=readtime[i];
248 if(!bSort)
250 fprintf(stderr,"Sorting disabled.\n");
252 else
254 sort_files(fnms,settime,nfiles);
256 /* Write out the new order and start times */
257 fprintf(stderr,"\nSummary of files and start times used:\n\n"
258 " File Start time Time step\n"
259 "---------------------------------------------------------\n");
260 for(i=0;i<nfiles;i++)
261 switch(cont_type[i])
263 case TIME_EXPLICIT:
264 fprintf(stderr,"%25s %10.3f %s %10.3f %s",
265 fnms[i],
266 conv_time(oenv,settime[i]),get_time_unit(oenv),
267 conv_time(oenv,timestep[i]),get_time_unit(oenv));
268 if ( i>0 &&
269 cont_type[i-1]==TIME_EXPLICIT && settime[i]==settime[i-1] )
270 fprintf(stderr," WARNING: same Start time as previous");
271 fprintf(stderr,"\n");
272 break;
273 case TIME_CONTINUE:
274 fprintf(stderr,"%25s Continue from last file\n",fnms[i]);
275 break;
276 case TIME_LAST:
277 fprintf(stderr,"%25s Change by same amount as last file\n",
278 fnms[i]);
279 break;
281 fprintf(stderr,"\n");
283 settime[nfiles]=FLT_MAX;
284 cont_type[nfiles]=TIME_EXPLICIT;
285 readtime[nfiles]=FLT_MAX;
288 static void do_demux(int nset, char *fnms[], char *fnms_out[], int nval,
289 real **value, real *time, real dt_remd, int isize,
290 atom_id index[], real dt, const output_env_t oenv)
292 int i, j, k, natoms, nnn;
293 int *fp_in, *fp_out;
294 bool bCont, *bSet;
295 real t, first_time = 0;
296 t_trxframe *trx;
298 snew(fp_in,nset);
299 snew(trx,nset);
300 snew(bSet,nset);
301 natoms = -1;
302 t = -1;
303 for (i = 0; (i < nset); i++)
305 nnn = read_first_frame(oenv, &(fp_in[i]), fnms[i], &(trx[i]),
306 TRX_NEED_X);
307 if (natoms == -1)
309 natoms = nnn;
310 first_time = trx[i].time;
312 else if (natoms != nnn)
314 gmx_fatal(FARGS,"Trajectory file %s has %d atoms while previous trajs had %d atoms" ,fnms[i],nnn,natoms);
316 if (t == -1)
318 t = trx[i].time;
320 else if (t != trx[i].time)
322 gmx_fatal(FARGS,"Trajectory file %s has time %f while previous trajs had time %f",fnms[i],trx[i].time,t);
326 snew(fp_out,nset);
327 for(i=0; (i<nset); i++)
329 fp_out[i] = open_trx(fnms_out[i],"w");
331 k = 0;
332 if (gmx_nint(time[k] - t) != 0)
334 gmx_fatal(FARGS,"First time in demuxing table does not match trajectories");
338 while ((k+1 < nval) && ((trx[0].time - time[k+1]) > dt_remd*0.1))
340 k++;
342 if (debug)
344 fprintf(debug,"trx[0].time = %g, time[k] = %g\n",trx[0].time,time[k]);
346 for(i=0; (i<nset); i++)
348 bSet[i] = FALSE;
350 for(i=0; (i<nset); i++)
352 j = gmx_nint(value[i][k]);
353 range_check(j,0,nset);
354 if (bSet[j])
356 gmx_fatal(FARGS,"Demuxing the same replica %d twice at time %f",
357 j,trx[0].time);
359 bSet[j] = TRUE;
361 if (dt==0 || bRmod(trx[i].time,first_time,dt))
363 if (index)
365 write_trxframe_indexed(fp_out[j],&trx[i],isize,index,NULL);
367 else
369 write_trxframe(fp_out[j],&trx[i],NULL);
374 bCont = (k < nval);
375 for(i=0; (i<nset); i++)
377 bCont = bCont && read_next_frame(oenv,fp_in[i],&trx[i]);
379 } while (bCont);
381 for(i=0; (i<nset); i++)
383 close_trx(fp_in[i]);
384 close_trx(fp_out[i]);
388 int gmx_trjcat(int argc, char *argv[])
390 const char
391 *desc[] =
393 "trjcat concatenates several input trajectory files in sorted order. ",
394 "In case of double time frames the one in the later file is used. ",
395 "By specifying [TT]-settime[tt] you will be asked for the start time ",
396 "of each file. The input files are taken from the command line, ",
397 "such that a command like [TT]trjcat -o fixed.trr *.trr[tt] should do ",
398 "the trick. Using [TT]-cat[tt] you can simply paste several files ",
399 "together without removal of frames with identical time stamps.[PAR]",
400 "One important option is inferred when the output file is amongst the",
401 "input files. In that case that particular file will be appended to",
402 "which implies you do not need to store double the amount of data.",
403 "Obviously the file to append to has to be the one with lowest starting",
404 "time since one can only append at the end of a file.[PAR]",
405 "If the [TT]-demux[tt] option is given, the N trajectories that are",
406 "read, are written in another order as specified in the xvg file."
407 "The xvg file should contain something like:[PAR]",
408 "0 0 1 2 3 4 5[BR]",
409 "2 1 0 2 3 5 4[BR]",
410 "Where the first number is the time, and subsequent numbers point to",
411 "trajectory indices.",
412 "The frames corresponding to the numbers present at the first line",
413 "are collected into the output trajectory. If the number of frames in",
414 "the trajectory does not match that in the xvg file then the program",
415 "tries to be smart. Beware." };
416 static bool bVels = TRUE;
417 static int prec = 3;
418 static bool bCat = FALSE;
419 static bool bSort = TRUE;
420 static bool bKeepLast = FALSE;
421 static bool bKeepLastAppend = FALSE;
422 static bool bOverwrite = FALSE;
423 static bool bSetTime = FALSE;
424 static bool bDeMux;
425 static real begin = -1;
426 static real end = -1;
427 static real dt = 0;
429 t_pargs
430 pa[] =
432 { "-b", FALSE, etTIME,
433 { &begin }, "First time to use (%t)" },
434 { "-e", FALSE, etTIME,
435 { &end }, "Last time to use (%t)" },
436 { "-dt", FALSE, etTIME,
437 { &dt }, "Only write frame when t MOD dt = first time (%t)" },
438 { "-prec", FALSE, etINT,
439 { &prec }, "Precision for .xtc and .gro writing in number of decimal places" },
440 { "-vel", FALSE, etBOOL,
441 { &bVels }, "Read and write velocities if possible" },
442 { "-settime", FALSE, etBOOL,
443 { &bSetTime }, "Change starting time interactively" },
444 { "-sort", FALSE, etBOOL,
445 { &bSort }, "Sort trajectory files (not frames)" },
446 { "-keeplast", FALSE, etBOOL,
447 { &bKeepLast }, "keep overlapping frames at end of trajectory" },
448 { "-overwrite", FALSE, etBOOL,
449 { &bOverwrite }, "overwrite overlapping frames during appending" },
450 { "-cat", FALSE, etBOOL,
451 { &bCat }, "do not discard double time frames" } };
452 #define npargs asize(pa)
453 int status, ftpin, i, frame, frame_out, step = 0, trjout = 0;
454 rvec *x, *v;
455 real xtcpr, t_corr;
456 t_trxframe fr, frout;
457 char **fnms, **fnms_out, *in_file, *out_file;
458 int n_append;
459 int trxout = -1;
460 bool bNewFile, bIndex, bWrite;
461 int earliersteps, nfile_in, nfile_out, *cont_type, last_ok_step;
462 real *readtime, *timest, *settime;
463 real first_time = 0, lasttime = NOTSET, last_ok_t = -1, timestep;
464 real last_frame_time, searchtime;
465 int isize, j;
466 atom_id *index = NULL, imax;
467 char *grpname;
468 real **val = NULL, *t = NULL, dt_remd;
469 int n, nset,bOK;
470 off_t fpos;
471 output_env_t oenv;
472 t_filenm fnm[] =
474 { efTRX, "-f", NULL, ffRDMULT },
475 { efTRO, "-o", NULL, ffWRMULT },
476 { efNDX, "-n", "index", ffOPTRD },
477 { efXVG, "-demux", "remd", ffOPTRD } };
479 #define NFILE asize(fnm)
481 CopyRight(stderr, argv[0]);
482 parse_common_args(&argc, argv, PCA_BE_NICE | PCA_TIME_UNIT, NFILE, fnm,
483 asize(pa), pa, asize(desc), desc, 0, NULL, &oenv);
485 bIndex = ftp2bSet(efNDX, NFILE, fnm);
486 bDeMux = ftp2bSet(efXVG, NFILE, fnm);
487 bSort = bSort && !bDeMux;
489 imax = NO_ATID;
490 if (bIndex)
492 printf("Select group for output\n");
493 rd_index(ftp2fn(efNDX, NFILE, fnm), 1, &isize, &index, &grpname);
494 /* scan index */
495 imax = index[0];
496 for (i = 1; i < isize; i++)
498 imax = max(imax, index[i]);
501 if (bDeMux)
503 nset = 0;
504 dt_remd = 0;
505 val = read_xvg_time(opt2fn("-demux", NFILE, fnm), TRUE,
506 opt2parg_bSet("-b", npargs, pa), begin,
507 opt2parg_bSet("-e", npargs, pa), end, 1, &nset, &n,
508 &dt_remd, &t);
509 printf("Read %d sets of %d points, dt = %g\n\n", nset, n, dt_remd);
510 if (debug)
512 fprintf(debug, "Dump of replica_index.xvg\n");
513 for (i = 0; (i < n); i++)
515 fprintf(debug, "%10g", t[i]);
516 for (j = 0; (j < nset); j++)
518 fprintf(debug, " %3d", gmx_nint(val[j][i]));
520 fprintf(debug, "\n");
524 /* prec is in nr of decimal places, xtcprec is a multiplication factor: */
525 xtcpr = 1;
526 for (i = 0; i < prec; i++)
528 xtcpr *= 10;
531 nfile_in = opt2fns(&fnms, "-f", NFILE, fnm);
532 if (!nfile_in)
534 gmx_fatal(FARGS,"No input files!" );
537 if (bDeMux && (nfile_in != nset))
539 gmx_fatal(FARGS,"You have specified %d files and %d entries in the demux table",nfile_in,nset);
542 nfile_out = opt2fns(&fnms_out,"-o",NFILE,fnm);
543 if (!nfile_out)
545 gmx_fatal(FARGS,"No output files!");
547 if ((nfile_out > 1) && !bDeMux)
549 gmx_fatal(FARGS,"Don't know what to do with more than 1 output file if not demultiplexing");
551 else if (bDeMux && (nfile_out != nset) && (nfile_out != 1))
553 gmx_fatal(FARGS,"Number of output files should be 1 or %d (#input files), not %d",nset,nfile_out);
555 if (bDeMux)
557 if (nfile_out != nset)
559 char *buf = strdup(fnms_out[0]);
560 snew(fnms_out,nset);
561 for(i=0; (i<nset); i++)
563 snew(fnms_out[i],strlen(buf)+32);
564 sprintf(fnms_out[i],"%d_%s",i,buf);
567 do_demux(nfile_in,fnms,fnms_out,n,val,t,dt_remd,isize,index,dt,oenv);
569 else
571 snew(readtime,nfile_in+1);
572 snew(timest,nfile_in+1);
573 scan_trj_files(fnms,nfile_in,readtime,timest,imax,oenv);
575 snew(settime,nfile_in+1);
576 snew(cont_type,nfile_in+1);
577 edit_files(fnms,nfile_in,readtime,timest,settime,cont_type,bSetTime,bSort,
578 oenv);
580 /* Check whether the output file is amongst the input files
581 * This has to be done after sorting etc.
583 out_file = fnms_out[0];
584 n_append = -1;
585 for(i=0; ((i<nfile_in) && (n_append==-1)); i++)
587 if (strcmp(fnms[i],out_file) == 0)
589 n_append = i;
592 if (n_append == 0) {
593 fprintf(stderr,"Will append to %s rather than creating a new file\n",
594 out_file);
596 else if (n_append != -1)
598 gmx_fatal(FARGS,"Can only append to the first file which is %s (not %s)",
599 fnms[0],out_file);
601 earliersteps=0;
603 /* Not checking input format, could be dangerous :-) */
604 /* Not checking output format, equally dangerous :-) */
606 frame=-1;
607 frame_out=-1;
608 /* the default is not to change the time at all,
609 * but this is overridden by the edit_files routine
611 t_corr=0;
613 if (n_append == -1)
615 trxout = open_trx(out_file,"w");
616 memset(&frout,0,sizeof(frout));
618 else
620 if (!read_first_frame(oenv,&status,out_file,&fr,FLAGS))
621 gmx_fatal(FARGS,"Reading first frame from %s",out_file);
622 if (!bKeepLast && !bOverwrite)
624 fprintf(stderr, "\n\nWARNING: Appending without -overwrite implies -keeplast "
625 "between the first two files. \n"
626 "If the trajectories have an overlap and have not been written binary \n"
627 "reproducible this will produce an incorrect trajectory!\n\n");
629 /* Fails if last frame is incomplete
630 * We can't do anything about it without overwriting
631 * */
632 if (gmx_fio_getftp(status) == efXTC)
634 lasttime = xdr_xtc_get_last_frame_time(gmx_fio_getfp(status),gmx_fio_getxdr(status),fr.natoms,&bOK);
635 fr.time = lasttime;
636 if (!bOK)
638 gmx_fatal(FARGS,"Error reading last frame. Maybe seek not supported." );
641 else
643 while (read_next_frame(oenv,status,&fr))
645 lasttime = fr.time;
647 bKeepLastAppend = TRUE;
648 close_trj(status);
649 trxout = open_trx(out_file,"a");
651 else if (bOverwrite)
653 if (gmx_fio_getftp(status) != efXTC) {
654 gmx_fatal(FARGS,"Overwrite only supported for XTC." );
656 last_frame_time = xdr_xtc_get_last_frame_time(gmx_fio_getfp(status),gmx_fio_getxdr(status),fr.natoms,&bOK);
657 if (!bOK)
659 gmx_fatal(FARGS,"Error reading last frame. Maybe seek not supported." );
661 /* xtc_seek_time broken for trajectories containing only 1 or 2 frames
662 * or when seek time = 0 */
663 if (nfile_in>1 && settime[1]<last_frame_time+timest[0]*0.5)
665 /* Jump to one time-frame before the start of next
666 * trajectory file */
667 searchtime = settime[1]-timest[0]*1.25;
669 else
671 searchtime = last_frame_time;
673 if (xtc_seek_time(searchtime,status,fr.natoms))
675 gmx_fatal(FARGS,"Error seeking to append position.");
677 read_next_frame(oenv,status,&fr);
678 if (fabs(searchtime - fr.time) > timest[0]*0.5)
680 gmx_fatal(FARGS,"Error seeking: attempted to seek to %f but got %f.",
681 searchtime,fr.time);
683 lasttime = fr.time;
684 fpos = gmx_fio_ftell(status);
685 close_trj(status);
686 trxout = open_trx(out_file,"r+");
687 if (gmx_fio_seek(trxout,fpos)) {
688 gmx_fatal(FARGS,"Error seeking to append position.");
691 printf("\n Will append after %f \n",lasttime);
692 frout = fr;
694 /* Lets stitch up some files */
695 timestep = timest[0];
696 for(i=n_append+1; (i<nfile_in); i++)
698 /* Open next file */
700 /* set the next time from the last frame in previous file */
701 if (i > 0)
703 if (frame_out >= 0)
705 if(cont_type[i]==TIME_CONTINUE)
707 begin =frout.time;
708 begin += 0.5*timestep;
709 settime[i]=frout.time;
710 cont_type[i]=TIME_EXPLICIT;
712 else if(cont_type[i]==TIME_LAST)
714 begin=frout.time;
715 begin += 0.5*timestep;
717 /* Or, if the time in the next part should be changed by the
718 * same amount, start at half a timestep from the last time
719 * so we dont repeat frames.
721 /* I don't understand the comment above, but for all the cases
722 * I tried the code seems to work properly. B. Hess 2008-4-2.
725 /* Or, if time is set explicitly, we check for overlap/gap */
726 if(cont_type[i]==TIME_EXPLICIT)
728 if( ( i < nfile_in ) &&
729 ( frout.time < settime[i]-1.5*timestep ) )
731 fprintf(stderr, "WARNING: Frames around t=%f %s have a different "
732 "spacing than the rest,\n"
733 "might be a gap or overlap that couldn't be corrected "
734 "automatically.\n",conv_time(oenv,frout.time),
735 get_time_unit(oenv));
740 /* if we don't have a timestep in the current file, use the old one */
741 if ( timest[i] != 0 )
743 timestep = timest[i];
745 read_first_frame(oenv,&status,fnms[i],&fr,FLAGS);
746 if(!fr.bTime)
748 fr.time=0;
749 fprintf(stderr,"\nWARNING: Couldn't find a time in the frame.\n");
752 if(cont_type[i]==TIME_EXPLICIT)
754 t_corr=settime[i]-fr.time;
756 /* t_corr is the amount we want to change the time.
757 * If the user has chosen not to change the time for
758 * this part of the trajectory t_corr remains at
759 * the value it had in the last part, changing this
760 * by the same amount.
761 * If no value was given for the first trajectory part
762 * we let the time start at zero, see the edit_files routine.
765 bNewFile=TRUE;
767 printf("\n");
768 if (lasttime != NOTSET)
770 printf("lasttime %g\n", lasttime);
775 /* copy the input frame to the output frame */
776 frout=fr;
777 /* set the new time by adding the correct calculated above */
778 frout.time += t_corr;
779 /* quit if we have reached the end of what should be written */
780 if((end > 0) && (frout.time > end+GMX_REAL_EPS))
782 i=nfile_in;
783 break;
786 /* determine if we should write this frame (dt is handled elsewhere) */
787 if (bCat) /* write all frames of all files */
789 bWrite = TRUE;
791 else if ( bKeepLast || (bKeepLastAppend && i==1))
792 /* write till last frame of this traj
793 and skip first frame(s) of next traj */
795 bWrite = ( frout.time > lasttime+0.5*timestep );
797 else /* write till first frame of next traj */
799 bWrite = ( frout.time < settime[i+1]-0.5*timestep );
802 if( bWrite && (frout.time >= begin) )
804 frame++;
805 if (frame_out == -1)
806 first_time = frout.time;
807 lasttime = frout.time;
808 if (dt==0 || bRmod(frout.time,first_time,dt))
810 frame_out++;
811 last_ok_t=frout.time;
812 if(bNewFile)
814 fprintf(stderr,"\nContinue writing frames from %s t=%g %s, "
815 "frame=%d \n",
816 fnms[i],conv_time(oenv,frout.time),get_time_unit(oenv),
817 frame);
818 bNewFile=FALSE;
821 if (bIndex)
823 write_trxframe_indexed(trxout,&frout,isize,index,NULL);
825 else
827 write_trxframe(trxout,&frout,NULL);
829 if ( ((frame % 10) == 0) || (frame < 10) )
831 fprintf(stderr," -> frame %6d time %8.3f %s \r",
832 frame_out,conv_time(oenv,frout.time),get_time_unit(oenv));
836 } while( read_next_frame(oenv,status,&fr));
838 close_trj(status);
840 earliersteps+=step;
842 if (trxout >= 0)
844 close_trx(trxout);
846 fprintf(stderr,"\nLast frame written was %d, time %f %s\n",
847 frame,conv_time(oenv,last_ok_t),get_time_unit(oenv));
849 thanx(stderr);
851 return 0;