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