randomseries.cc 8.08 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*! \file randomseries.cc
 * \brief provide time series of incoherent random numbers
 * 
 * ----------------------------------------------------------------------------
 * 
 * \author Thomas Forbriger
 * \date 31/10/2019
 * 
 * provide time series of incoherent random numbers
 * 
 * Copyright (c) 2019 by Thomas Forbriger (BFO Schiltach) 
 * 
 * REVISIONS and CHANGES 
 *  - 31/10/2019   V1.0   Thomas Forbriger
15
 *  - 02/10/2020   V1.1   pass seed value to rng
16
17
18
19
 * 
 * ============================================================================
 */
#define RANDOMSERIES_VERSION \
20
  "RANDOMSERIES   V1.1   provide time series of incoherent random numbers"
21
22

#include <iostream>
23
24
25
#include <fstream>
#include <string>
#include <sstream>
26
27
#include <tfxx/commandline.h>
#include <tfxx/seitosh.h>
28
29
30
31
#include <tfxx/error.h>
#include <tfxx/rng.h>
#include <aff/series.h>
#include <aff/iterator.h>
32
33
34
35
36
37
#include <datrwxx/writeany.h>

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

38
39
40
/* ---------------------------------------------------------------------- */

struct Options {
41
  bool verbose, overwrite, setseed;
42
43
44
45
46
47
48
49
  std::string rngtype, filename, filetype;
  int nseries, nsamples;
  double std, mean, dt;
  long unsigned int seed;
}; // struct Options

/* ---------------------------------------------------------------------- */

50
51
52
53
54
55
56
int main(int iargc, char* argv[])
{

  // define usage information
  char usage_text[]=
  {
    RANDOMSERIES_VERSION "\n"
57
    "usage: randomseries filename [-v] [-rngtype t] [-t type] [-o]" "\n"
58
    "                    [-nseries n] [-nsamples n] [-dt v]" "\n"
59
    "                    [-std v] [-mean v] [-seed n]" "\n"
60
    "                    [-rngtype rng]" "\n"
61
62
63
64
65
66
67
68
    "   or: randomseries --help|-h" "\n"
    "   or: randomseries --xhelp[=type]\n"
  };

  // define full help text
  char help_text[]=
  {
    "-help		print description\n"
69
70
71
72
73
74
75
    "-xhelp[=type] print detailed information\n"
    "             if 'type' is not specfied, or equals 'all', print\n"
    "               information regarding all supported file formats\n"
    "             if 'type' is specified, just print text for file\n"
    "               format 'type'\n"
    "             if 'type' is 'gslrng' print recommendations regarding\n"
    "               random number generator type\n"
76
77
78
79
    "\n"
    "filename     name of output file\n"
    "-v           be verbose\n"
    "-o           overwrite existing output file\n"
80
81
82
83
    "-rngtype t   select random number generator type\n"
    "             run\n"
    "               randomseries -xhelp=gslrng\n"
    "             to see comments\n"
84
85
86
    "-t type      select output file type\n"
    "-nseries n   produce 'n' time series\n"
    "-nsamples n  produce 'n' samples per series\n"
87
    "-dt v        set sampling interval to 'v' seconds\n"
88
    "-rngtype rng select random number generator\n"
89
90
91
    "-seed n      initialize random number generator with 'n'\n"
    "-std v       set standard deviation to 'v'\n"
    "-mean v      set mean value of samples to 'v'\n"
92
93
94
95
96
97
98
99
100
101
102
103
    "\n"
    "The program uses the GSL (GNU Scientific Library) random number\n"
    "generators. See https://www.gnu.org/software/gsl/doc/html/rng.html\n"
    "\n"
    "The programs main purpose is to provide several time series\n"
    "which are incoherent (as far as possible). All samples are taken\n"
    "sequentially from the random number generator with the generator\n"
    "being seeded only at the very beginning. If several (incoherent)\n"
    "time series should be computed by individual calls to a random\n"
    "number generator program, this would require careful seeding\n"
    "for each program invocation to make sure that different sequences\n"
    "of samples are indeed independent or at least incoherent.\n"
104
105
    "If no seed value is passed to the program, the random number generator\n"
    "is seeded with the current system clock count.\n"
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
  };

  // define commandline options
  using namespace tfxx::cmdline;
  static Declare options[]= 
  {
    // 0: print help
    {"help",arg_no,"-"},
    // 1: verbose mode
    {"v",arg_no,"-"},
    // 2: overwrite existing output file
    {"o",arg_no,"-"},
    // 3: select output file type
    {"t",arg_yes,"sff"},
    // 4: select output file type
    {"nseries",arg_yes,"1"},
    // 5: select output file type
    {"nsamples",arg_yes,"10000"},
    // 6: select output file type
125
    {"seed",arg_yes,"0"},
126
127
128
129
130
131
    // 7: select output file type
    {"std",arg_yes,"1."},
    // 8: select output file type
    {"mean",arg_yes,"0."},
    // 9: output file format
    {"xhelp",arg_opt,"all"},
132
133
134
135
    // 10: output file format
    {"rngtype",arg_yes,"default"},
    // 11: sampling interval
    {"dt",arg_yes,"1."},
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
    {NULL}
  };

  // no arguments? print usage...
  if (iargc<2) 
  {
    cerr << usage_text << endl;
    cerr << endl << tfxx::seitosh::repository_reference << 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;
    cerr << endl;
    cerr << "supported output data file types:" << endl;
    datrw::supported_output_data_types(cerr);
    cerr << endl << tfxx::seitosh::repository_reference << endl;
    exit(0);
  }

  // help on file format details requested? 
  if (cmdline.optset(9))
  {
    cerr << usage_text << endl;
    cerr << endl;
    if (cmdline.string_arg(9) == "all")
    {
      datrw::online_help(cerr);
    }
171
172
173
174
175
176
177
    else if (cmdline.string_arg(9) == "gslrng")
    {
      cerr << tfxx::numeric::RNGgaussian::comment_gsl_rng_ranlux << endl;
      cerr << endl;
      cerr << "Available random number generator types:" << endl;
      tfxx::numeric::RNGgaussian::rng_list_types(cerr);
    }
178
179
180
181
182
183
184
    else
    {
      datrw::online_help(cmdline.string_arg(9), cerr);
    }
    exit(0);
  }

185
186
187
188
189
190
191
192
193
194
195
196
  TFXX_assert(cmdline.extra(), "Missing file name");
  
  // extract command line options
  Options opt;

  opt.filename=cmdline.next();
  opt.verbose=cmdline.optset(1);
  opt.overwrite=cmdline.optset(2);
  opt.filetype=cmdline.string_arg(3);
  opt.nseries=cmdline.int_arg(4);
  opt.nsamples=cmdline.int_arg(5);
  opt.seed=cmdline.int_arg(6);
197
  opt.setseed=cmdline.optset(6);
198
199
200
201
202
203
204
205
  opt.std=cmdline.double_arg(7);
  opt.mean=cmdline.double_arg(8);
  opt.rngtype=cmdline.string_arg(10);
  opt.dt=cmdline.double_arg(11);

  // check parameters
  TFXX_assert(opt.nseries>0, "number of series must be positive");
  TFXX_assert(opt.nsamples>0, "number of samples must be positive");
206
  TFXX_assert(opt.seed>=0, "seed value must be non-negative");
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
  TFXX_assert(opt.dt>0, "sampling interval must be positive");

  if (opt.verbose)
  {
    cout << RANDOMSERIES_VERSION << endl;
  }

  // open output file
  if (opt.verbose)
  {
    cout << "open output file " << opt.filename
      << " with format " << opt.filetype << endl;
  }
  if (!opt.overwrite) { datrw::abort_if_exists(opt.filename); }
  std::ofstream ofs(opt.filename.c_str(),
                    datrw::oanystream::openmode(opt.filetype));
  datrw::oanystream os(ofs, opt.filetype);

  // create random number generator
  tfxx::numeric::RNGgaussian rng(opt.std, opt.mean, opt.rngtype.c_str());
227
  if (opt.setseed) { rng.set(opt.seed); } else { rng.set(); }
228
229
  
  if (opt.verbose)
230
  {
231
232
233
234
235
236
237
238
    cout << "RNG parameters:\n"
      << " type: " << rng.type() << "\n"
      << " seed: " << rng.seed() << "\n"
      << " mean: " << rng.mean() << "\n"
      << " std:  " << rng.std() << endl;
    cout << "produce " << opt.nseries << " traces with "
      << opt.nsamples << " samples each" << endl;
    cout << "set sampling interval to " << opt.dt << " seconds" << endl;
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
  sff::WID2 wid2;
  wid2.nsamples=opt.nsamples;
  wid2.instype=opt.rngtype;
  wid2.station="RNG";
  wid2.dt=opt.dt;

  aff::Series<double> series(opt.nsamples);
  for (int iseries=0; iseries<opt.nseries; iseries++)
  {
    if (opt.verbose)
    {
      cout << "produce series #" << iseries+1 << endl;
    }
    aff::Iterator<aff::Series<double> > CS(series);
    while (CS.valid())
    {
      *CS = rng.value();
      ++CS;
    }
    std::ostringstream oss;
    oss << iseries+1;
    wid2.channel=oss.str();
    os << wid2;
    os << series;
  }
266
267
268
}

/* ----- END OF randomseries.cc ----- */