Jpp  18.2.1-ARCA-DF-PATCH
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& d = _hdr_dict();
224  if ( d.count(key) == 0 ) return -1;
225  auto v = d.at(key);
226  auto i = std::find (v.begin(), v.end(), field );
227  if (i == v.end()) return -1;
228  return i - v.begin();
229  }
230 
231  /**
232  * Get data with the given key at given field.\n
233  * This method throws a run-time exception if no field is available.
234  *
235  * Note that this method uses the dictionary define in method Head::_hdr_dict.
236  *
237  * \param key key
238  * \param field field
239  * \return data
240  */
242  {
243  int idx = get_index_of_field(key, field);
244 
245  if ( idx == -1 )
246  {
247  THROW(Exception, "Failed to find" << key << " " << field);
248  }
249 
250  return get_field( key, idx );
251  }
252 
253 
254  /**
255  * Set data with the given key at given field.\n
256  * This method throws a run-time exception if no field available.
257  *
258  * Note that this method uses the dictionary define in method Head::_hdr_dict.
259  *
260  * \param key key
261  * \param field field
262  * \param value vakue
263  */
264  void set_field( std::string key, std::string field, std::string value )
265  {
266  using namespace std;
267 
268  if ( field == "" ) get_line( key ) = value;
269 
270  int idx = get_index_of_field( key, field );
271 
272  if ( idx < 0 )
273  {
274  THROW(Exception, "GFailed to find field in header line: " << key << " " << field);
275  }
276 
277  vector<string> vals = splitstring( get_line( key ) );
278 
279  // if the fields before do not exist, add padding
280  while ( int( vals.size() ) <= idx ) vals.push_back("0");
281 
282  vals[idx] = value;
283  ostringstream ss;
284 
285  for (unsigned i = 0; i < vals.size() ; i++ )
286  {
287  ss << vals[i];
288  if ( i != vals.size() - 1) ss << " ";
289  }
290  set_line( key, ss.str() );
291 
292  }
293 
294  /**
295  * Print header.
296  *
297  * \param out output stream
298  */
299  void print ( std::ostream& out = std::cout ) const
300  {
301  if (count("start_run")) out << "start_run: " << at("start_run") << std::endl;
302 
303  for ( auto& p : *this )
304  {
305  if ( p.first == "start_run" || p.first == "end_event" ) continue;
306  out << p.first << ": " << p.second << std::endl ;
307  }
308  out << "end_event:" << std::endl;
309  }
310 
311  /**
312  * Get internal description of the known lines in header.
313  *
314  * \return internal dictionary
315  */
317  {
318  using namespace std;
319 
320  // map with, for each tag (key), a vector of field-names
321 
322  static map<string, vector<string> > r;
323  if ( r.size() > 0 ) return r;
324 
325  string desc =
326  "DAQ:livetime\n"
327  "cut_primary cut_seamuon cut_in cut_nu:Emin Emax cosTmin cosTmax\n"
328  "generator physics simul:program version date time\n"
329  "seed:program level iseed\n"
330  "PM1_type_area:type area TTS\n"
331  "PDF:i1 i2\n"
332  "model:interaction muon scattering numberOfEnergyBins\n"
333  "can:zmin zmax r\n"
334  "genvol:zmin zmax r volume numberOfEvents\n"
335  "merge:time gain\n"
336  "coord_origin:x y z\n"
337  "translate:x y z\n"
338  "genhencut:gDir Emin\n"
339  "k40:rate time\n" // note lower-case k
340  "K40:livetime\n" // note capital K
341  "norma:primaryFlux numberOfPrimaries\n"
342  "livetime:numberOfSeconds errorOfSeconds\n"
343  "flux:type key file_1 file_2\n"
344  "spectrum:alpha\n"
345  "fixedcan:xcenter ycenter zmin zmax radius\n"
346  "start_run:run_id";
347 
348  for ( auto line : splitstring(desc, '\n') )
349  {
350  auto v = splitstring( line, ':');
351 
352  vector< string > fields = splitstring( v[1] );
353  for ( auto key : splitstring( v[0] ) )
354  {
355  r[key] = fields;
356  }
357  }
358  return r;
359  }
360 
361 
362  /**
363  * Get the number of generated events needed for computing event rates.
364  *
365  * \return number of events
366  */
367  double ngen() const
368  {
369  return stod ( get_field("genvol", "numberOfEvents") );
370  }
371 
372  /**
373  * Get the the live time provided by the DAQ sytstem (=number of processed timeslices * frametime).
374  *
375  * \return live time [s]
376  */
377  double daq_livetime() const
378  {
379  return stod ( get_field("DAQ", "livetime") );
380  }
381 
382 
383  /**
384  * Get the Monte Carlo live time
385  *
386  * \return live time [s]
387  */
388  double mc_livetime() const
389  {
390  return stod ( get_field("livetime", "numberOfSeconds") );
391  }
392 
393  /**
394  * Get coordinate origin.
395  *
396  * \return position
397  */
399  {
400  return Vec( stod( get_field("coord_origin", "x") ),
401  stod( get_field("coord_origin", "y") ),
402  stod( get_field("coord_origin", "z") ));
403  }
404 
405  /**
406  * Get coordinate translation.
407  *
408  * \return translation
409  */
410  Vec translate() const
411  {
412  return Vec( stod( get_field("translate", "x") ),
413  stod( get_field("translate", "y") ),
414  stod( get_field("translate", "z") ));
415  }
416 
417  virtual ~Head() {}
418 
419  /**
420  * Action method at file open.
421  *
422  * \param version version
423  */
424  static void actionAtFileOpen(int version)
425  {
427  }
428 
429  static int ROOT_IO_VERSION; //!< Streamer version as obtained from ROOT file.
430 
431  ClassDef(Head, 2 );
432 };
433 
434 
435 /**
436  * Print header.
437  *
438  * \param out output stream
439  * \param h header
440  * \return output stream
441  */
442 inline std::ostream& operator<<(std::ostream& out, const Head& h)
443 {
444  h.print(out);
445  return out;
446 }
447 
448 
449 #endif
virtual ~Head()
Definition: Head.hh:417
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:264
std::string get_field(std::string key, std::string field) const
Get data with the given key at given field.
Definition: Head.hh:241
version
Definition: JEditTuneHV.sh:5
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:712
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:388
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:868
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:299
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:429
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:367
then JMuonMCEvt f $INPUT_FILE o $INTERMEDIATE_FILE d
Definition: JMuonPath.sh:47
General exception.
Definition: Exception.hh:13
std::string to_string(const T &value)
Convert value to string.
static const std::map< std::string, std::vector< std::string > > & _hdr_dict()
Get internal description of the known lines in header.
Definition: Head.hh:316
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:424
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:377
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:866
Vec translate() const
Get coordinate translation.
Definition: Head.hh:410
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:398