tidofi.cc 18 KB
Newer Older
thomas.forbriger's avatar
thomas.forbriger committed
1
2
3
4
5
6
7
8
9
10
11
/*! \file tidofi.cc
 * \brief time domain filter
 * 
 * ----------------------------------------------------------------------------
 * 
 * \author Thomas Forbriger
 * \date 17/02/2004
 * 
 * time domain filter
 * 
 * Copyright (c) 2004 by Thomas Forbriger (BFO Schiltach) 
thomas.forbriger's avatar
thomas.forbriger committed
12
13
 *
 * ----
thomas.forbriger's avatar
thomas.forbriger committed
14
 * TIDOFI is free software; you can redistribute it and/or modify
thomas.forbriger's avatar
thomas.forbriger committed
15
16
17
18
19
20
21
22
23
24
25
26
27
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version. 
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * ----
thomas.forbriger's avatar
thomas.forbriger committed
28
29
30
 * 
 * REVISIONS and CHANGES 
 *  - 17/02/2004   V1.0   Thomas Forbriger
thomas.forbriger's avatar
thomas.forbriger committed
31
 *  - 18/12/2007   V1.1   hunting bugs...
32
 *  - 21.12.2010   V1.2   implement output file type option
33
 *  - 27.07.2011   V1.3   implement apply trace modifier
34
 *  - 08.09.2011   V1.4   support format modifiers
35
36
37
 *  - 26.01.2012   V1.5   
 *                        - write header data only if supported by output 
 *                          format
38
 *                        - implemented offset variable tapers
39
40
41
 *  - 25.02.2019   V1.6   take return value of filter function in order to
 *                        allow a change of number of samples or sampling
 *                        interval
thomas.forbriger's avatar
thomas.forbriger committed
42
43
44
45
 * 
 * ============================================================================
 */
#define TIDOFI_VERSION \
46
  "TIDOFI   V1.6   time domain filter"
thomas.forbriger's avatar
thomas.forbriger committed
47
48

#include <iostream>
thomas.forbriger's avatar
thomas.forbriger committed
49
50
#include <fstream>
#include <string>
thomas.forbriger's avatar
thomas.forbriger committed
51
#include <tfxx/commandline.h>
thomas.forbriger's avatar
thomas.forbriger committed
52
53
#include <tfxx/xcmdline.h>
#include <tfxx/error.h>
thomas.forbriger's avatar
thomas.forbriger committed
54
#include <tfxx/stringfunc.h>
thomas.forbriger's avatar
thomas.forbriger committed
55
56
#include <tfxx/rangestring.h>
#include <tfxx/rangelist.h>
thomas.forbriger's avatar
thomas.forbriger committed
57
#include <tfxx/misc.h>
thomas.forbriger's avatar
thomas.forbriger committed
58
#include <tsxx/anyfilter.h>
59
#include <datrwxx/readany.h>
60
#include <datrwxx/writeany.h>
thomas.forbriger's avatar
thomas.forbriger committed
61
#include <sffxx.h>
thomas.forbriger's avatar
thomas.forbriger committed
62
#include <sffostream.h>
thomas.forbriger's avatar
thomas.forbriger committed
63
#include <aff/dump.h>
64
#include <tsxx/ovtaper.h>
thomas.forbriger's avatar
thomas.forbriger committed
65
66
67
68
69

using std::cout;
using std::cerr;
using std::endl;

thomas.forbriger's avatar
thomas.forbriger committed
70
71
72
typedef ts::filter::Ttimeseries Ttimeseries;
typedef Ttimeseries::Tseries Tseries;

thomas.forbriger's avatar
thomas.forbriger committed
73
74
75
/*----------------------------------------------------------------------*/

struct Options {
thomas.forbriger's avatar
thomas.forbriger committed
76
  bool verbose, debug, debugdump;
thomas.forbriger's avatar
thomas.forbriger committed
77
78
79
80
  bool overwrite;
  bool readcommandfile;
  std::string commandfile;
  bool readstdin;
81
  std::string inputformat, outputformat;
thomas.forbriger's avatar
thomas.forbriger committed
82
83
84
85
}; // struct Options

/*======================================================================*/

thomas.forbriger's avatar
thomas.forbriger committed
86
87
88
89
90
91
92
int main(int iargc, char* argv[])
{

  // define usage information
  char usage_text[]=
  {
    TIDOFI_VERSION "\n"
93
    "usage: tidofi [-v] [-o] [-cf file] [-cs] [-type type] [-Type type]" "\n"
94
95
    "              outfile infile [t:T|a:T] [f:F] [prft:file] [poft:file]\n"
    "                [infile [t:T|a:T] [f:F] [prft:file] [poft:file] ... ]" "\n"
thomas.forbriger's avatar
thomas.forbriger committed
96
    "   or: tidofi --help|-h" "\n"
97
    "   or: tidofi --xhelp" "\n"
thomas.forbriger's avatar
thomas.forbriger committed
98
99
100
101
102
  };

  // define full help text
  char help_text[]=
  {
thomas.forbriger's avatar
thomas.forbriger committed
103
104
105
106
    "outfile      name of file to contain results" "\n"
    "infile       input file" "\n"
    "             t:T select traces T, where T may be any range" "\n"
    "                 specification like \'3-4\' or \'5,6,7-12,20\'" "\n"
107
108
    "             f:F specifies an input file format differing from" "\n"
    "                 the format selected by \"-type\"" "\n"
109
110
111
    "             a:T apply filter to traces T, where T may be any range" "\n"
    "                 specification like \'3-4\' or \'5,6,7-12,20\'" "\n"
    "                 all other traces are passed to the output unchanged\n"
112
113
114
115
116
117
    "             prft:file\n"
    "                 pre-filter taper from file to be applied before\n"
    "                 filtering traces\n"
    "             poft:file\n"
    "                 post-filter taper from file to be applied before\n"
    "                 filtering traces\n"
118
119
    "             file mofifiers t and a are mutually exclusive, where a\n"
    "             has higher precendence\n"
120
121
122
    "             prft and poft taper parameters are read from \"file\"\n"
    "             taper parameter file is expected in format produced\n"
    "             by refract\n"
123
124
    "\n"
    "-xhelp       print detailed information regarding file formats" "\n"
thomas.forbriger's avatar
thomas.forbriger committed
125
    "-v           be verbose" "\n"
thomas.forbriger's avatar
thomas.forbriger committed
126
127
    "-DEBUG       produce debug output" "\n"
    "-DUMP        produce debug dumps" "\n"
thomas.forbriger's avatar
thomas.forbriger committed
128
129
130
    "-o           overwrite output" "\n"
    "-cf file     read filter commands from \"file\"" "\n"
    "-cs          read filter commands from stdin" "\n"
131
132
    "-type type   choose input file format (default: sff)" "\n"
    "-Type type   choose output file format (default: sff)" "\n"
thomas.forbriger's avatar
thomas.forbriger committed
133
134
135
136
    "\n"
    "In command files comment lines may either commence with \"rem\" like" "\n"
    "in seife command files or with \'#\'. The seife command \"end\" is" "\n"
    "simply ignored (like a comment line)."
thomas.forbriger's avatar
thomas.forbriger committed
137
138
139
140
141
142
143
144
145
146
  };

  // define commandline options
  using namespace tfxx::cmdline;
  static Declare options[]= 
  {
    // 0: print help
    {"help",arg_no,"-"},
    // 1: verbose mode
    {"v",arg_no,"-"},
thomas.forbriger's avatar
thomas.forbriger committed
147
148
149
150
151
152
    // 2: overwrite mode
    {"o",arg_no,"-"},
    // 3: command file
    {"cf",arg_yes,"-"},
    // 4: stdin mode
    {"cs",arg_no,"-"},
thomas.forbriger's avatar
thomas.forbriger committed
153
    // 5: input file format
154
    {"type",arg_yes,"sff"},
thomas.forbriger's avatar
thomas.forbriger committed
155
    // 6: generate debug output
thomas.forbriger's avatar
thomas.forbriger committed
156
157
158
    {"DEBUG",arg_no,"-"},
    // 7: generate debug dumps
    {"DUMP",arg_no,"-"},
159
160
161
162
    // 8: output file format
    {"Type",arg_yes,"sff"},
    // 9: output file format
    {"xhelp",arg_no,"-"},
thomas.forbriger's avatar
thomas.forbriger committed
163
164
165
    {NULL}
  };

thomas.forbriger's avatar
thomas.forbriger committed
166
  static const char tracekey[]="t";
167
  static const char applykey[]="a";
168
  static const char formatkey[]="f";
169
170
  static const char prefiltertaperkey[]="prft";
  static const char postfiltertaperkey[]="poft";
thomas.forbriger's avatar
thomas.forbriger committed
171

thomas.forbriger's avatar
thomas.forbriger committed
172
  // define commandline argument modifier keys
173
174
  static const char* cmdlinekeys[]
    ={tracekey, formatkey, applykey, prefiltertaperkey, postfiltertaperkey, 0};
thomas.forbriger's avatar
thomas.forbriger committed
175

thomas.forbriger's avatar
thomas.forbriger committed
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
  // no arguments? print usage...
  if (iargc<2) 
  {
    cerr << usage_text << endl;
    exit(0);
  }

  // collect options from commandline
  Commandline cmdline(iargc, argv, options);

  // help requested? print full help text...
  if (cmdline.optset(0))
  {
    cerr << usage_text << endl;
    cerr << help_text << endl;
191
    datrw::supported_data_types(cerr); 
192
193
    cerr << endl;
    ts::filter::print_any_help(cerr);
thomas.forbriger's avatar
thomas.forbriger committed
194
195
196
    exit(0);
  }

197
198
199
200
201
202
203
204
205
  // help on file format details requested? 
  if (cmdline.optset(9))
  {
    cerr << usage_text << endl;
    cerr << endl;
    datrw::online_help(cerr); 
    exit(0);
  }

thomas.forbriger's avatar
thomas.forbriger committed
206
207
208
209
210
211
212
  // extract commandline options
  Options opt;
  opt.verbose=cmdline.optset(1);
  opt.overwrite=cmdline.optset(2);
  opt.readcommandfile=cmdline.optset(3);
  opt.commandfile=cmdline.string_arg(3);
  opt.readstdin=cmdline.optset(4);
thomas.forbriger's avatar
thomas.forbriger committed
213
  opt.inputformat=cmdline.string_arg(5);
thomas.forbriger's avatar
thomas.forbriger committed
214
  opt.debug=cmdline.optset(6);
thomas.forbriger's avatar
thomas.forbriger committed
215
  opt.debugdump=cmdline.optset(7);
216
217
  opt.outputformat=cmdline.string_arg(8);
  // 9 is --xhelp
thomas.forbriger's avatar
thomas.forbriger committed
218
219

  if (opt.verbose)
220
  { cout << TIDOFI_VERSION << endl; }
thomas.forbriger's avatar
thomas.forbriger committed
221

thomas.forbriger's avatar
thomas.forbriger committed
222
223
224
225
226
  // extract commandline arguments
  TFXX_assert(cmdline.extra(), "missing output file");
  std::string outfile=cmdline.next();
  TFXX_assert(cmdline.extra(), "missing input file");
  tfxx::cmdline::Tparsed arguments=parse_cmdline(cmdline, cmdlinekeys);
thomas.forbriger's avatar
thomas.forbriger committed
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
  if ((arguments.size()>1) && opt.verbose)
  {
    cout << "NOTICE: file specific information (SRCE line and file FREE)" <<
      endl
      <<    "        will be taken from first file only!" << endl;
  }

  /*----------------------------------------------------------------------*/
  // first of all read the filter commands
  // we use an sff FREE block to store the lines - its so easy
  sff::FREE filtercommands;
  if (opt.readcommandfile)
  {
    if (opt.verbose) 
    {
      cout << "read filter commands from file \"" 
        << opt.commandfile << "\"" << endl;
    }
    std::ifstream ifs(opt.commandfile.c_str());
    while (ifs.good())
    {
      std::string line;
      getline(ifs, line);
      line=tfxx::string::trimws(line);
      if (line.size() > 0)
      {
        filtercommands.append(line);
        if (opt.verbose) 
        { cout << ">> " << line << endl; }
      }
    }
  }
  // read commands from stdin
  if (opt.readstdin)
  {
    if (opt.verbose) 
    {
      cout << "read filter commands from stdin (terminate with ctrl-D)"  
        << endl;
    }
    while (std::cin.good())
    {
      std::string line;
      getline(std::cin, line);
      line=tfxx::string::trimws(line);
      if (line.size() > 0)
      {
        filtercommands.append(line);
        if (opt.verbose) 
        { cout << ">> " << line << endl; }
      }
    }
  }

  /*----------------------------------------------------------------------*/
  // strip comments etc from filter commands
thomas.forbriger's avatar
thomas.forbriger committed
283
  // and create filter object
thomas.forbriger's avatar
thomas.forbriger committed
284
  sff::FREE commands;
thomas.forbriger's avatar
thomas.forbriger committed
285
  ts::filter::FilterCollection filter;
thomas.forbriger's avatar
thomas.forbriger committed
286
287
288
289
290
291
  {
    sff::FREE::Tlines::const_iterator line=filtercommands.lines.begin();
    while (line != filtercommands.lines.end())
    {
      // skip comments
      bool skip=false;
thomas.forbriger's avatar
thomas.forbriger committed
292
293
      TFXX_debug(opt.debug, "main", 
                 "skip " + *line + " if irrelevant" );
thomas.forbriger's avatar
thomas.forbriger committed
294
295
296
297
298
299
300
301
302
303
304
305
306
      skip |= (line->substr(0,1)=="#");
      skip |= (line->substr(0,3)=="rem");
      skip |= (line->substr(0,3)=="end");
      if (!skip) { 
        std::string command=(*line);
        // replace comma by space
        std::string::size_type i=command.find(",",i);
        while (i!=std::string::npos)
        {
          command.replace(i,1," ");
          i=command.find(",",i+1);
        }
        commands.append(command); 
thomas.forbriger's avatar
thomas.forbriger committed
307
308
309
310
311
312
        filter.push_back(ts::filter::make_any_filter(command, opt.debug));
      }
      else
      {
        TFXX_debug(opt.debug, "main", 
                   "skip " + *line + "!" );
thomas.forbriger's avatar
thomas.forbriger committed
313
314
315
316
      }
      ++line;
    }
  }
thomas.forbriger's avatar
thomas.forbriger committed
317
  // TFXX_debug(opt.debug, "main", "STOP" ); exit(0);
thomas.forbriger's avatar
thomas.forbriger committed
318
319
320
321
322
323
324

  /*----------------------------------------------------------------------*/
  // prepare file FREE block
  sff::FREE filefree;
  {
    filefree.append(TIDOFI_VERSION);
    std::string line;
thomas.forbriger's avatar
thomas.forbriger committed
325
    if (opt.readcommandfile || opt.readstdin)
thomas.forbriger's avatar
thomas.forbriger committed
326
    {
thomas.forbriger's avatar
thomas.forbriger committed
327
328
      line="commands are read from";
      if (opt.readstdin)
thomas.forbriger's avatar
thomas.forbriger committed
329
      {
thomas.forbriger's avatar
thomas.forbriger committed
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
        line += " stdin";
        if (opt.readcommandfile)
        {
          line += " (first) and";
        }
        else
        {
          line += ":";
        }
      }
      filefree.append(line);
      line.clear();
      if (opt.readcommandfile) 
      {
        line += "file \"" + opt.commandfile + "\":";
        filefree.append(line);
      }
      if (filtercommands.lines.size() > 0)
      {
        filefree.append(filtercommands);
      }
      else
      {
        filefree.append("  command list is empty!");
thomas.forbriger's avatar
thomas.forbriger committed
354
355
      }
    }
thomas.forbriger's avatar
thomas.forbriger committed
356
    else
thomas.forbriger's avatar
thomas.forbriger committed
357
    {
thomas.forbriger's avatar
thomas.forbriger committed
358
      filefree.append("no filtercommands were read");
thomas.forbriger's avatar
thomas.forbriger committed
359
360
    }
    filefree.append("output file name:");
thomas.forbriger's avatar
thomas.forbriger committed
361
    filefree.append("  " + outfile);
thomas.forbriger's avatar
thomas.forbriger committed
362
363
364
365
366
367
    filefree.append("input file selection:");
    tfxx::cmdline::Tparsed::const_iterator file=arguments.begin();
    while (file != arguments.end())
    {
      filefree.append("  " + file->name);
      line="  ";
thomas.forbriger's avatar
thomas.forbriger committed
368
      tfxx::cmdline::Toptionmap::const_iterator option=file->options.begin();
thomas.forbriger's avatar
thomas.forbriger committed
369
370
      while (option != file->options.end())
      {
thomas.forbriger's avatar
thomas.forbriger committed
371
        line += "  " + option->first + ":" + option->second;
thomas.forbriger's avatar
thomas.forbriger committed
372
373
374
375
        ++option;
      }
      if (line.size()>2) { filefree.append(line); }
      ++file;
thomas.forbriger's avatar
thomas.forbriger committed
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
    }
    if (arguments.size()>1)
    {
      filefree.append("In cases where more than one input file is read,");
      filefree.append("the SRCE line is taken from the first file only (if");
      filefree.append("present there).");
    }
  }

  /*======================================================================*/
  // start processing

  // open output file
  // ----------------
  if (opt.verbose) { cout << "open output file " << outfile << endl; }
  // check if output file exists and open
  if (!opt.overwrite)
  {
    std::ifstream file(outfile.c_str(),std::ios_base::in);
    TFXX_assert((!file.good()),"ERROR: output file exists!");
  }
397
  std::ios_base::openmode oopenmode
398
    =datrw::oanystream::openmode(opt.outputformat);
399
  std::ofstream ofs(outfile.c_str(), oopenmode);
400
  datrw::oanystream os(ofs, opt.outputformat, opt.debug);
thomas.forbriger's avatar
thomas.forbriger committed
401
402
403
404
405
406
407
408
409
410

  // set flag to process header of first input file
  bool firstfile=true;
  // cycle through all input files
  // -----------------------------
  tfxx::cmdline::Tparsed::const_iterator infile=arguments.begin();
  while (infile != arguments.end())
  {
    // open input file
    if (opt.verbose) { cout << "open input file " << infile->name << endl; }
411
    std::string inputformat=opt.inputformat;
412
413
    if (infile->haskey(formatkey)) 
    {
414
      inputformat=infile->value(formatkey);
415
416
417
418
419
    }
    std::ios_base::openmode iopenmode
      =datrw::ianystream::openmode(inputformat);
    std::ifstream ifs(infile->name.c_str(), iopenmode);
    datrw::ianystream is(ifs, inputformat);
420
421
422
423
424
425
426

    // read tapers
    // -----------
    bool applyprefiltertaper=infile->haskey(prefiltertaperkey);
    bool applypostfiltertaper=infile->haskey(postfiltertaperkey);
    
    // create taper objects here
427
428
429
    ts::tapers::OffsetVariableTaper prefiltertaper;
    ts::tapers::OffsetVariableTaper postfiltertaper;

430
431
432
433
434
    // read taper parameters here
    if (applyprefiltertaper)
    {
      std::string taperfilename
        =infile->value(prefiltertaperkey);
435
      prefiltertaper.read(taperfilename);
436
437
438
439
440
    }
    if (applypostfiltertaper)
    {
      std::string taperfilename
        =infile->value(postfiltertaperkey);
441
      postfiltertaper.read(taperfilename);
442
443
    }
      
thomas.forbriger's avatar
thomas.forbriger committed
444
    // handle file header
445
446
    // ------------------
    sff::SRCE insrceline;
447
    bool srceavailable=false;
thomas.forbriger's avatar
thomas.forbriger committed
448
449
450
451
452
453
454
455
456
    if (firstfile)
    {
      if (is.hasfree()) 
      { 
        sff::FREE infilefree;
        is >> infilefree;
        filefree.append("block read from first input file:");
        filefree.append(infilefree);
      }
457
      if (os.handlesfilefree()) { os << filefree; }
thomas.forbriger's avatar
thomas.forbriger committed
458
      if (is.hassrce())
thomas.forbriger's avatar
thomas.forbriger committed
459
460
      {
        is >> insrceline;
461
        srceavailable=true;
462
        if (os.handlessrce()) { os << insrceline; }
thomas.forbriger's avatar
thomas.forbriger committed
463
464
465
466
467
      }
    }

    // cycle through traces of input file
    // ----------------------------------
thomas.forbriger's avatar
thomas.forbriger committed
468
469
470
    // setup trace selection
    typedef tfxx::RangeList<int> Trangelist;
    bool doselect=infile->haskey(tracekey);
471
    bool doapply=infile->haskey(applykey);
thomas.forbriger's avatar
thomas.forbriger committed
472
473
    Trangelist traceranges=
      tfxx::string::rangelist<Trangelist::Tvalue>(infile->value(tracekey));
474
475
476
477
478
479
480
481
482
483
484
485
486
    // apply has precedence
    if (doapply)
    {
      if (opt.verbose && doselect)
      {
        std::cout << "  trace \"apply\" modifier has precedence "
          << "over trace \"selection\" modifier."
          << std::endl;
      }
      doselect=false;
      traceranges
        =tfxx::string::rangelist<Trangelist::Tvalue>(infile->value(applykey));
    } 
thomas.forbriger's avatar
thomas.forbriger committed
487
488
489
490
491
492
    int itrace=0;
    while (is.good())
    {
      ++itrace;
      if ((!doselect) || traceranges.contains(itrace))
      {
thomas.forbriger's avatar
thomas.forbriger committed
493
        TFXX_debug(opt.debug, "main", "process trace #" << itrace );
thomas.forbriger's avatar
thomas.forbriger committed
494
        if (opt.verbose)
495
        { std::cout << "  process trace #" << itrace << ":"; }
thomas.forbriger's avatar
thomas.forbriger committed
496
497
        Tseries series;
        is >> series;
thomas.forbriger's avatar
thomas.forbriger committed
498
499
500
501
502
503
        if (opt.debugdump)
        {
          TFXX_debug(opt.debugdump, "main", 
                     "  input series:");
          DUMP(series);
        }
thomas.forbriger's avatar
thomas.forbriger committed
504
505
        sff::WID2 wid2;
        is >> wid2;
thomas.forbriger's avatar
thomas.forbriger committed
506
507
        TFXX_debug(opt.debug, "main", 
                   "  series and WID2 are read");
508
509
510
511
512
        sff::INFO info; 
        if (is.hasinfo()) 
        { 
          is >> info; 
        }
513
        // apply filter only if requested
514
        // ------------------------------
515
        if ((!doapply) || traceranges.contains(itrace))
thomas.forbriger's avatar
thomas.forbriger committed
516
        {
517
518
519
520
521
522
523
524
525
526
          double offset, t0, T;
          if (applyprefiltertaper || applypostfiltertaper)
          {
            TFXX_assert(is.hasinfo() && srceavailable,
                        "Offset variable taper requires source and receiver "
                        "coordinates");
            offset=::sff::offset(insrceline, info);
            t0=libtime::time2double(insrceline.date-wid2.date);
            T=wid2.dt*wid2.nsamples;
          }
527
528
529
          if (applyprefiltertaper)
          {
            // apply pre-filter taper
530
531
532
            ts::tapers::FourPoint taper
              =prefiltertaper.taper(offset, t0, T);
            taper.apply(series);
533
          }
534
          series=filter(Ttimeseries(series, wid2.dt), opt.debug);
535
536
537
          if (applypostfiltertaper)
          {
            // apply post-filter taper
538
539
540
            ts::tapers::FourPoint taper
              =postfiltertaper.taper(offset, t0, T);
            taper.apply(series);
541
          }
542
543
544
545
546
547
548
549
550
          TFXX_debug(opt.debug, "main", 
                     "  series is filtered");
          if (opt.debugdump)
          {
            TFXX_debug(opt.debugdump, "main", 
                       "  output series:");
            DUMP(series);
          }
          if (opt.verbose) { std::cout << " filtered" << std::endl; }
551
        // ------------------------------
552
553
554
555
        }
        else
        {
          if (opt.verbose) { std::cout << " passed unchanged" << std::endl; }
thomas.forbriger's avatar
thomas.forbriger committed
556
        }
557
        wid2.nsamples=series.size();
thomas.forbriger's avatar
thomas.forbriger committed
558
        os << wid2;
thomas.forbriger's avatar
thomas.forbriger committed
559
560
        TFXX_debug(opt.debug, "main", 
                   "  series and WID are written");
561
562
563
564
        if (is.hasinfo()) 
        { 
          if (os.handlesinfo()) { os << info; }
        }
565
        if (is.hasfree() || true) 
thomas.forbriger's avatar
thomas.forbriger committed
566
567
568
569
570
        {
          sff::FREE tracefree;
          is >> tracefree;
          tracefree.append(TIDOFI_VERSION);
          tracefree.append("read from file " + infile->name);
571
572
573
574
575
576
577
578
          if ((!doapply) || traceranges.contains(itrace))
          {
            tracefree.append(commands);
          }
          else
          {
            tracefree.append("passed unchanged");
          }
579
          if (os.handlestracefree()) { os << tracefree; } 
thomas.forbriger's avatar
thomas.forbriger committed
580
        }
thomas.forbriger's avatar
thomas.forbriger committed
581
582
        TFXX_debug(opt.debug, "main", 
                   "trace #" << itrace << " successfully processed");
583
        os << series;
thomas.forbriger's avatar
thomas.forbriger committed
584
585
586
      }
      else
      {
thomas.forbriger's avatar
thomas.forbriger committed
587
        TFXX_debug(opt.debug, "main", "skip trace #" << itrace );
thomas.forbriger's avatar
thomas.forbriger committed
588
589
590
591
592
593
594
        if (opt.verbose)
        { std::cout << "     skip trace #" << itrace << std::endl; }
        is.skipseries();
      }
    }
    
    // go to next file
thomas.forbriger's avatar
thomas.forbriger committed
595
596
    firstfile=false;
    ++infile;
thomas.forbriger's avatar
thomas.forbriger committed
597
598
  }

thomas.forbriger's avatar
thomas.forbriger committed
599
600
601
}

/* ----- END OF tidofi.cc ----- */