Jpp test-rotations-old
the software that should make you happy
Loading...
Searching...
No Matches
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 */
22static 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 */
43inline 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 */
64struct 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
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 */
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 */
441inline std::ostream& operator<<(std::ostream& out, const Head& h)
442{
443 h.print(out);
444 return out;
445}
446
447
448#endif
static void trimstring(std::string &s)
Trim a string in place.
Definition Head.hh:22
std::ostream & operator<<(std::ostream &out, const Head &h)
Print header.
Definition Head.hh:441
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.
General exception.
Definition Exception.hh:13
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
std::string & get_line(std::string key)
Get data with the given key.
Definition Head.hh:101
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
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
const std::string & get_line(std::string key) const
Get data with the given key.
Definition Head.hh:89
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
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
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
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_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
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
The Vec class is a straightforward 3-d vector, which also works in pyroot.
Definition Vec.hh:13