Jpp  17.3.1
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Head.hh
Go to the documentation of this file.
1 #ifndef HEAD_HH_INCLUDED
2 #define HEAD_HH_INCLUDED
3 
6 
7 #include "TObject.h"
8 
9 #include <string>
10 #include <sstream>
11 #include <iostream>
12 #include <map>
13 #include <algorithm>
14 #include <vector>
15 
16 
17 /**
18  * Trim a string in place
19  *
20  * \param s input string
21  * \return list of tokens
22  */
23 static inline void trimstring(std::string &s)
24 {
25  // from the left
26  s.erase( s.begin(), std::find_if(s.begin(), s.end(), [](int ch) {
27  return !std::isspace(ch);
28  }));
29 
30  // from the right
31  s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
32  return !std::isspace(ch);
33  }).base(), s.end());
34 }
35 
36 /**
37  * Split string at delimiter. Trailing and leading whitespace is removed from each token.
38  * Empty tokens are not put in the output list.
39  *
40  * \param str input string
41  * \param delim token delimiter
42  * \return list of tokens
43  */
44 inline std::vector<std::string> splitstring(const std::string& str, char delim = ' ')
45 {
46  using namespace std;
47 
49 
50  stringstream ss(str);
51  string token;
52  while (getline(ss, token, delim))
53  {
54  trimstring(token);
55  if (token != "") r.push_back(token);
56  }
57 
58  return r;
59 }
60 
61 
62 /**
63  * The Head class reflects the header of Monte-Carlo event files, which consists of keys (also referred to as "tags") and values.
64  */
65 struct Head : public TObject, std::map<std::string, std::string>
66 {
67  struct tags {
68  static constexpr const char* const UUID = "UUID";
69  };
70 
71 
72  /**
73  * Check availability of data with the given key.
74  *
75  * \param key key
76  * \return true if data are available; else false
77  */
78  bool have_line (std::string key ) const
79  {
80  return count( key ) != 0;
81  }
82 
83  /**
84  * Get data with the given key.\n
85  * This method throws a run-time exception if no data are available.
86  *
87  * \param key key
88  * \return data
89  */
90  const std::string& get_line( std::string key ) const
91  {
92  return this->at(key);
93  }
94 
95  /**
96  * Get data with the given key.\n
97  * This method throws a run-time exception if no data are available.
98  *
99  * \param key key
100  * \return data
101  */
103  {
104  return this->at(key);
105  }
106 
107 
108  /**
109  * In case of duplicate keys, they are internally stored in the map
110  * with a suffix "_n". This function returns all the keys that start
111  * with 'key' and end in "_n", with n an integer
112  *
113  * \param tag tag (without suffix)
114  */
115 
117  {
119 
120  auto match = [&] (const std::string & key) {
121 
122  if (key == tag) return true;
123 
124  if ( key.find( tag ) != 0 ) return false;
125 
126  // what is left should be of the form _d(ddd)
127  std::string left = key.substr( tag.length(), key.length() );
128  if (left.length() < 2 || left[0] != '_' ) return false ;
129  for ( unsigned i = 1; i < left.length(); i++ )
130  {
131  if (!std::isdigit( left[i] )) return false ;
132  }
133  return true;
134  };
135 
136  for ( auto& p : *this )
137  {
138  if ( match( p.first ) ) r.push_back( p.first );
139  }
140 
141  return r;
142  }
143 
144 
145 
146 
147  /**
148  * Get all data compatible with the given key. This means all data
149  * that is internally stored with "key_n", with n an integer \n
150  * This method throws a run-time exception if no data are available.
151  *
152  * \param tag tag (without suffix)
153  * \return data
154  */
156  {
158 
159  for ( auto& key : matching_keys( tag ) ) {
160  r.push_back( get_line( key ) );
161  }
162 
163  return r;
164  }
165 
166 
167  /**
168  * Set data with the given tag. The function will return the actual key that
169  * is used internally to store the result, which is equal to the tag with an
170  * optional "_n" added to ensure uniqueness.
171  *
172  * \param tag tag
173  * \param line data
174  * \param ensure_unique add '_n' (with n an integer) to the tag if it would overwrite an existing key.
175  */
176 
177  std::string set_line( std::string tag, std::string line , bool ensure_unique = true )
178  {
179  std::string k = tag;
180 
181  if (ensure_unique)
182  for (int i = 1; find(k) != end() ; i++)
183  {
184  k = tag + "_" + std::to_string(i);
185  }
186 
188  return k;
189  }
190 
191  /**
192  * Get data with the given key at given index.\n
193  * This method throws a run-time exception if no data are available.
194  *
195  * \param key key
196  * \param idx index
197  * \return data
198  */
199  std::string get_field( std::string key, int idx ) const
200  {
201  using namespace std;
202 
204 
205  if ( idx < 0 || idx >= int ( v.size() ) )
206  {
207  THROW(Exception, "Cannot find word number " << idx << " in line " << get_line(key) << " for key: " << key);
208  }
209  return v[idx];
210  }
211 
212  /**
213  * Get index of data with the given key at given field.\n
214  *
215  * Note that this method uses the dictionary define in method Head::_hdr_dict.
216  *
217  * \param key key
218  * \param field field
219  * \return index (-1 if not present)
220  */
222  {
223  auto v = _hdr_dict()[key];
224  auto i = std::find (v.begin(), v.end(), field );
225  if (i == v.end()) return -1;
226  return i - v.begin();
227  }
228 
229  /**
230  * Get data with the given key at given field.\n
231  * This method throws a run-time exception if no field is available.
232  *
233  * Note that this method uses the dictionary define in method Head::_hdr_dict.
234  *
235  * \param key key
236  * \param field field
237  * \return data
238  */
240  {
241  int idx = get_index_of_field(key, field);
242 
243  if ( idx == -1 )
244  {
245  THROW(Exception, "Failed to find" << key << " " << field);
246  }
247 
248  return get_field( key, idx );
249  }
250 
251 
252  /**
253  * Set data with the given key at given field.\n
254  * This method throws a run-time exception if no field available.
255  *
256  * Note that this method uses the dictionary define in method Head::_hdr_dict.
257  *
258  * \param key key
259  * \param field field
260  * \param value vakue
261  */
262  void set_field( std::string key, std::string field, std::string value )
263  {
264  using namespace std;
265 
266  if ( field == "" ) get_line( key ) = value;
267 
268  int idx = get_index_of_field( key, field );
269 
270  if ( idx < 0 )
271  {
272  THROW(Exception, "GFailed to find field in header line: " << key << " " << field);
273  }
274 
275  vector<string> vals = splitstring( get_line( key ) );
276 
277  // if the fields before do not exist, add padding
278  while ( int( vals.size() ) <= idx ) vals.push_back("0");
279 
280  vals[idx] = value;
281  ostringstream ss;
282 
283  for (unsigned i = 0; i < vals.size() ; i++ )
284  {
285  ss << vals[i];
286  if ( i != vals.size() - 1) ss << " ";
287  }
288  set_line( key, ss.str() );
289 
290  }
291 
292  /**
293  * Print header.
294  *
295  * \param out output stream
296  */
297  void print ( std::ostream& out = std::cout ) const
298  {
299  if (count("start_run")) out << "start_run: " << at("start_run") << std::endl;
300 
301  for ( auto& p : *this )
302  {
303  if ( p.first == "start_run" || p.first == "end_event" ) continue;
304  out << p.first << ": " << p.second << std::endl ;
305  }
306  out << "end_event:" << std::endl;
307  }
308 
309  /**
310  * Get internal description of the known lines in header.
311  *
312  * \return internal dictionary
313  */
315  {
316  using namespace std;
317 
318  // map with, for each tag (key), a vector of field-names
319 
320  static map<string, vector<string> > r;
321  if ( r.size() > 0 ) return r;
322 
323  string desc =
324  "DAQ:livetime\n"
325  "cut_primary cut_seamuon cut_in cut_nu:Emin Emax cosTmin cosTmax\n"
326  "generator physics simul:program version date time\n"
327  "seed:program level iseed\n"
328  "PM1_type_area:type area TTS\n"
329  "PDF:i1 i2\n"
330  "model:interaction muon scattering numberOfEnergyBins\n"
331  "can:zmin zmax r\n"
332  "genvol:zmin zmax r volume numberOfEvents\n"
333  "merge:time gain\n"
334  "coord_origin:x y z\n"
335  "translate:x y z\n"
336  "genhencut:gDir Emin\n"
337  "k40:rate time\n"
338  "norma:primaryFlux numberOfPrimaries\n"
339  "livetime:numberOfSeconds errorOfSeconds\n"
340  "flux:type key file_1 file_2\n"
341  "spectrum:alpha\n"
342  "fixedcan:xcenter ycenter zmin zmax radius\n"
343  "start_run:run_id";
344 
345  for ( auto line : splitstring(desc, '\n') )
346  {
347  auto v = splitstring( line, ':');
348 
349  vector< string > fields = splitstring( v[1] );
350  for ( auto key : splitstring( v[0] ) )
351  {
352  r[key] = fields;
353  }
354  }
355  return r;
356  }
357 
358 
359  /**
360  * Get the number of generated events needed for computing event rates.
361  *
362  * \return number of events
363  */
364  double ngen() const
365  {
366  return stod ( get_field("genvol", "numberOfEvents") );
367  }
368 
369  /**
370  * Get the the live time provided by the DAQ sytstem (=number of processed timeslices * frametime).
371  *
372  * \return live time [s]
373  */
374  double daq_livetime() const
375  {
376  return stod ( get_field("DAQ", "livetime") );
377  }
378 
379 
380  /**
381  * Get the Monte Carlo live time
382  *
383  * \return live time [s]
384  */
385  double mc_livetime() const
386  {
387  return stod ( get_field("livetime", "numberOfSeconds") );
388  }
389 
390  /**
391  * Get coordinate origin.
392  *
393  * \return position
394  */
396  {
397  return Vec( stod( get_field("coord_origin", "x") ),
398  stod( get_field("coord_origin", "y") ),
399  stod( get_field("coord_origin", "z") ));
400  }
401 
402  /**
403  * Get coordinate translation.
404  *
405  * \return translation
406  */
407  Vec translate() const
408  {
409  return Vec( stod( get_field("translate", "x") ),
410  stod( get_field("translate", "y") ),
411  stod( get_field("translate", "z") ));
412  }
413 
414  virtual ~Head() {}
415 
416  /**
417  * Action method at file open.
418  *
419  * \param version version
420  */
421  static void actionAtFileOpen(int version)
422  {
424  }
425 
426  static int ROOT_IO_VERSION; //!< Streamer version as obtained from ROOT file.
427 
428  ClassDef(Head, 2 );
429 };
430 
431 
432 /**
433  * Print header.
434  *
435  * \param out output stream
436  * \param h header
437  * \return output stream
438  */
439 inline std::ostream& operator<<(std::ostream& out, const Head& h)
440 {
441  h.print(out);
442  return out;
443 }
444 
445 
446 #endif
virtual ~Head()
Definition: Head.hh:414
then fatal No hydrophone data file $HYDROPHONE_TXT fi sort gr k
static constexpr const char *const UUID
Definition: Head.hh:68
std::string & get_line(std::string key)
Get data with the given key.
Definition: Head.hh:102
void set_field(std::string key, std::string field, std::string value)
Set data with the given key at given field.
Definition: Head.hh:262
std::string get_field(std::string key, std::string field) const
Get data with the given key at given field.
Definition: Head.hh:239
version
Definition: JEditTuneHV.sh:5
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:696
bool have_line(std::string key) const
Check availability of data with the given key.
Definition: Head.hh:78
Definition: JRoot.hh:19
double mc_livetime() const
Get the Monte Carlo live time.
Definition: Head.hh:385
int get_index_of_field(std::string key, std::string field) const
Get index of data with the given key at given field.
Definition: Head.hh:221
data_type r[M+1]
Definition: JPolint.hh:779
ClassDef(Head, 2)
std::vector< std::string > matching_keys(const std::string &tag) const
In case of duplicate keys, they are internally stored in the map with a suffix &quot;_n&quot;.
Definition: Head.hh:116
The Vec class is a straightforward 3-d vector, which also works in pyroot.
Definition: Vec.hh:12
void print(std::ostream &out=std::cout) const
Print header.
Definition: Head.hh:297
then awk string
std::istream & getline(std::istream &in, JString &object)
Read string from input stream until end of line.
Definition: JString.hh:478
std::string set_line(std::string tag, std::string line, bool ensure_unique=true)
Set data with the given tag.
Definition: Head.hh:177
static int ROOT_IO_VERSION
Streamer version as obtained from ROOT file.
Definition: Head.hh:426
static void trimstring(std::string &s)
Trim a string in place.
Definition: Head.hh:23
The Head class reflects the header of Monte-Carlo event files, which consists of keys (also referred ...
Definition: Head.hh:65
double ngen() const
Get the number of generated events needed for computing event rates.
Definition: Head.hh:364
General exception.
Definition: Exception.hh:13
std::string to_string(const T &value)
Convert value to string.
const std::string & get_line(std::string key) const
Get data with the given key.
Definition: Head.hh:90
static void actionAtFileOpen(int version)
Action method at file open.
Definition: Head.hh:421
std::ostream & operator<<(std::ostream &stream, const CLBCommonHeader &header)
std::vector< std::string > get_lines(const std::string &tag) const
Get all data compatible with the given key.
Definition: Head.hh:155
double daq_livetime() const
Get the the live time provided by the DAQ sytstem (=number of processed timeslices * frametime)...
Definition: Head.hh:374
std::string get_field(std::string key, int idx) const
Get data with the given key at given index.
Definition: Head.hh:199
data_type v[N+1][M+1]
Definition: JPolint.hh:777
Vec translate() const
Get coordinate translation.
Definition: Head.hh:407
std::vector< std::string > splitstring(const std::string &str, char delim= ' ')
Split string at delimiter.
Definition: Head.hh:44
Vec coord_origin() const
Get coordinate origin.
Definition: Head.hh:395
static std::map< std::string, std::vector< std::string > > & _hdr_dict()
Get internal description of the known lines in header.
Definition: Head.hh:314