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