CMS 3D CMS Logo

PayloadInspector.h
Go to the documentation of this file.
1 #ifndef CondCore_Utilities_PayloadInspector_h
2 #define CondCore_Utilities_PayloadInspector_h
3 
6 #include <iostream>
7 
8 #include <string>
9 #include <tuple>
10 #include <vector>
11 #include <boost/python/list.hpp>
12 #include <boost/python/extract.hpp>
13 
14 namespace cond {
15 
16  namespace payloadInspector {
17 
18  // Metadata dictionary
19  struct PlotAnnotations {
20  static constexpr const char* const PLOT_TYPE_K = "type";
21  static constexpr const char* const TITLE_K = "title";
22  static constexpr const char* const PAYLOAD_TYPE_K = "payload_type";
23  static constexpr const char* const INFO_K = "info";
24  static constexpr const char* const XAXIS_K = "x_label";
25  static constexpr const char* const YAXIS_K = "y_label";
26  static constexpr const char* const ZAXIS_K = "z_label";
28  std::string get( const std::string& key ) const;
29  std::map<std::string,std::string> m;
30  bool singleIov = false;
31  };
32 
33  static const char* const JSON_FORMAT_VERSION = "1.0";
34 
35  // Serialize functions
36  template <typename V> std::string serializeValue( const std::string& entryLabel, const V& value ){
37  std::stringstream ss;
38  ss << "\""<<entryLabel<<"\":"<<value;
39  return ss.str();
40  }
41 
42  template <> std::string serializeValue( const std::string& entryLabel, const std::string& value ){
43  std::stringstream ss;
44  ss << "\""<<entryLabel<<"\":\""<<value<<"\"";
45  return ss.str();
46  }
47 
48  // Specialization for the multi-values coordinates ( to support the combined time+runlumi abscissa )
49  template <typename V> std::string serializeValue( const std::string& entryLabel, const std::tuple<V,std::string>& value ){
50  std::stringstream ss;
51  ss << serializeValue( entryLabel, std::get<0>(value) );
52  ss << ", ";
53  ss << serializeValue( entryLabel+"_label", std::get<1>(value) );
54  return ss.str();
55  }
56 
57  // Specialization for the error bars
58  template <typename V> std::string serializeValue( const std::string& entryLabel, const std::pair<V,V>& value ){
59  std::stringstream ss;
60  ss << serializeValue( entryLabel, value.first );
61  ss << ", ";
62  ss << serializeValue( entryLabel+"_err", value.second );
63  return ss.str();
64  }
65 
67  std::stringstream ss;
68  ss <<"\"version\": \""<<JSON_FORMAT_VERSION<<"\",";
69  ss <<"\"annotations\": {";
70  bool first = true;
71  for( auto a: annotations.m ){
72  if ( !first ) ss <<",";
73  ss << "\""<<a.first<<"\":\"" << a.second <<"\"";
74  first = false;
75  }
76  ss <<"}";
77  return ss.str();
78  }
79 
80  template <typename X,typename Y> std::string serialize( const PlotAnnotations& annotations, const std::vector<std::tuple<X,Y> >& data ){
81  // prototype implementation...
82  std::stringstream ss;
83  ss << "{";
84  ss << serializeAnnotations( annotations );
85  ss <<",";
86  ss << "\"data\": [";
87  bool first = true;
88  for ( auto d : data ){
89  if( !first ) ss <<",";
90  ss <<" { "<<serializeValue("x",std::get<0>(d))<<", "<<serializeValue( "y",std::get<1>( d))<<" }";
91  first = false;
92  }
93  ss << "]";
94  ss << "}";
95  return ss.str();
96  }
97 
98  template <typename X,typename Y,typename Z> std::string serialize( const PlotAnnotations& annotations, const std::vector<std::tuple<X,Y,Z> >& data ){
99  // prototype implementation...
100  std::stringstream ss;
101  ss << "{";
102  ss << serializeAnnotations( annotations );
103  ss <<",";
104  ss << "\"data\": [";
105  bool first = true;
106  for ( auto d : data ){
107  if( !first ) ss <<",";
108  ss <<" { "<<serializeValue("x",std::get<0>(d))<<", "<<serializeValue( "y",std::get<1>( d))<<", "<<serializeValue( "z",std::get<2>( d))<<" }";
109  first = false;
110  }
111  ss << "]";
112  ss << "}";
113  return ss.str();
114  }
115 
116  struct ModuleVersion {
117  static constexpr const char* const label = "1.0";
118  };
119 
120  // Base class, factorizing the functions exposed in the python interface
121  class PlotBase {
122  public:
123  PlotBase();
124 
125  // required in the browser to find corresponding tags
126  std::string payloadType() const;
127 
128  // required in the browser
129  std::string title() const;
130 
131  // required in the browser
132  std::string type() const;
133 
134  // required in the browser
135  bool isSingleIov() const;
136 
137  // returns the json file with the plot data
138  std::string data() const;
139 
140  // triggers the processing producing the plot
141  bool process( const std::string& connectionString, const std::string& tag, const std::string& timeType, cond::Time_t begin, cond::Time_t end );
142 
143  // not exposed in python:
144  // called internally in process()
145  virtual void init();
146 
147  // not exposed in python:
148  // called internally in process()
149  virtual std::string processData( const std::vector<std::tuple<cond::Time_t,cond::Hash> >& iovs );
150 
151  // to be set in order to limit the iov selection ( and processing ) to 1 iov
152  void setSingleIov( bool flag );
153 
154  // access to the fetch function of the configured reader, to be used in the processData implementations
155  template <typename PayloadType> std::shared_ptr<PayloadType> fetchPayload( const cond::Hash& payloadHash ){
156  return m_dbSession.fetchPayload<PayloadType>( payloadHash );
157  }
158 
159  // access to the timeType of the tag in process
160  cond::TimeType tagTimeType() const;
161 
162  // access to the underlying db session
163  cond::persistency::Session dbSession();
164 
165  protected:
166 
168 
169  private:
170 
173 
174  std::string m_data = "";
175  };
176 
177  // Concrete plot-types implementations
178  template <typename PayloadType, typename X, typename Y> class Plot2D : public PlotBase {
179  public:
180  Plot2D( const std::string& type, const std::string& title, const std::string xLabel, const std::string& yLabel ) :
181  PlotBase(),m_plotData(){
182  m_plotAnnotations.m[PlotAnnotations::PLOT_TYPE_K] = type;
183  m_plotAnnotations.m[PlotAnnotations::TITLE_K] = title;
184  m_plotAnnotations.m[PlotAnnotations::XAXIS_K] = xLabel;
185  m_plotAnnotations.m[PlotAnnotations::YAXIS_K] = yLabel;
186  m_plotAnnotations.m[PlotAnnotations::PAYLOAD_TYPE_K] = cond::demangledName( typeid(PayloadType) );
187  }
188 
190  return serialize( m_plotAnnotations, m_plotData);
191  }
192 
193  std::string processData( const std::vector<std::tuple<cond::Time_t,cond::Hash> >& iovs ) override {
194  fill( iovs );
195  return serializeData();
196  }
197 
198  std::shared_ptr<PayloadType> fetchPayload( const cond::Hash& payloadHash ){
199  return PlotBase::fetchPayload<PayloadType>( payloadHash );
200  }
201 
202  virtual bool fill( const std::vector<std::tuple<cond::Time_t,cond::Hash> >& iovs ) = 0;
203  protected:
204  std::vector<std::tuple<X,Y> > m_plotData;
205  };
206 
207  template <typename PayloadType, typename X, typename Y, typename Z> class Plot3D : public PlotBase {
208  public:
209  Plot3D( const std::string& type, const std::string& title, const std::string xLabel, const std::string& yLabel, const std::string& zLabel ) :
210  PlotBase(),m_plotData(){
211  m_plotAnnotations.m[PlotAnnotations::PLOT_TYPE_K] = type;
212  m_plotAnnotations.m[PlotAnnotations::TITLE_K] = title;
213  m_plotAnnotations.m[PlotAnnotations::XAXIS_K] = xLabel;
214  m_plotAnnotations.m[PlotAnnotations::YAXIS_K] = yLabel;
215  m_plotAnnotations.m[PlotAnnotations::ZAXIS_K] = zLabel;
216  m_plotAnnotations.m[PlotAnnotations::PAYLOAD_TYPE_K] = cond::demangledName( typeid(PayloadType) );
217  }
218 
220  return serialize( m_plotAnnotations, m_plotData);
221  }
222 
223  std::string processData( const std::vector<std::tuple<cond::Time_t,cond::Hash> >& iovs ) override {
224  fill( iovs );
225  return serializeData();
226  }
227 
228  std::shared_ptr<PayloadType> fetchPayload( const cond::Hash& payloadHash ){
229  return PlotBase::fetchPayload<PayloadType>( payloadHash );
230  }
231 
232  virtual bool fill( const std::vector<std::tuple<cond::Time_t,cond::Hash> >& iovs ) = 0;
233  protected:
234  std::vector<std::tuple<X,Y,Z> > m_plotData;
235  };
236 
237  template<typename PayloadType, typename Y> class HistoryPlot : public Plot2D<PayloadType,unsigned long long,Y > {
238  public:
240 
241  HistoryPlot( const std::string& title, const std::string& yLabel ) :
242  Base( "History", title, "iov_since" , yLabel ){
243  }
244 
245  bool fill( const std::vector<std::tuple<cond::Time_t,cond::Hash> >& iovs ) override {
246  for( auto iov : iovs ) {
247  std::shared_ptr<PayloadType> payload = Base::fetchPayload( std::get<1>(iov) );
248  if( payload.get() ){
249  Y value = getFromPayload( *payload );
250  Base::m_plotData.push_back( std::make_tuple(std::get<0>(iov),value));
251  }
252  }
253  return true;
254  }
255 
256  virtual Y getFromPayload( PayloadType& payload ) = 0;
257 
258  };
259 
260  template<typename PayloadType, typename Y> class RunHistoryPlot : public Plot2D<PayloadType,std::tuple<float,std::string>,Y > {
261  public:
263 
264  RunHistoryPlot( const std::string& title, const std::string& yLabel ) :
265  Base( "RunHistory", title, "iov_since" , yLabel ){
266  }
267 
268  bool fill( const std::vector<std::tuple<cond::Time_t,cond::Hash> >& iovs ) override {
269  // for the lumi iovs we need to count the number of lumisections in every runs
270  std::map<cond::Time_t,unsigned int> runs;
271  if( Base::tagTimeType()==cond::lumiid ){
272  for( auto iov : iovs ) {
273  unsigned int run = std::get<0>(iov) >> 32;
274  auto it = runs.find( run );
275  if( it == runs.end() ) it = runs.insert( std::make_pair( run, 0 ) ).first;
276  it->second++;
277  }
278  }
279  unsigned int currentRun = 0;
280  float lumiIndex = 0;
281  unsigned int lumiSize = 0;
282  unsigned int rind = 0;
283  float ind = 0;
284  std::string label("");
285  for( auto iov : iovs ) {
286  unsigned long long since = std::get<0>(iov);
287  // for the lumi iovs we squeeze the lumi section available in the constant run 'slot' of witdth=1
288  if( Base::tagTimeType()==cond::lumiid ){
289  unsigned int run = since >> 32;
290  unsigned int lumi = since & 0xFFFFFFFF;
291  if( run != currentRun ) {
292  rind++;
293  lumiIndex = 0;
294  auto it = runs.find( run );
295  if( it == runs.end() ) {
296  // it should never happen
297  return false;
298  }
299  lumiSize = it->second;
300  } else {
301  lumiIndex++;
302  }
303  ind = rind + (lumiIndex/lumiSize);
304  label = boost::lexical_cast<std::string>( run )+" : "+boost::lexical_cast<std::string>( lumi );
305  currentRun = run;
306  } else {
307  ind++;
308  // for the timestamp based iovs, it does not really make much sense to use this plot...
309  if( Base::tagTimeType()==cond::timestamp ){
310  boost::posix_time::ptime t = cond::time::to_boost( since );
311  label = boost::posix_time::to_simple_string( t );
312  } else {
313  label = boost::lexical_cast<std::string>( since );
314  }
315  }
316  std::shared_ptr<PayloadType> payload = Base::fetchPayload( std::get<1>(iov) );
317  if( payload.get() ){
318  Y value = getFromPayload( *payload );
319  Base::m_plotData.push_back( std::make_tuple(std::make_tuple(ind,label),value));
320  }
321  }
322  return true;
323  }
324 
325  virtual Y getFromPayload( PayloadType& payload ) = 0;
326 
327  };
328 
329  template<typename PayloadType, typename Y> class TimeHistoryPlot : public Plot2D<PayloadType,std::tuple<unsigned long long,std::string>,Y > {
330  public:
332 
333  TimeHistoryPlot( const std::string& title, const std::string& yLabel ) :
334  Base( "TimeHistory", title, "iov_since" , yLabel ){
335  }
336 
337  bool fill( const std::vector<std::tuple<cond::Time_t,cond::Hash> >& iovs ) override {
339  if( Base::tagTimeType()==cond::lumiid || Base::tagTimeType()==cond::runnumber){
340  cond::Time_t min = std::get<0>(iovs.front());
341  cond::Time_t max = std::get<0>( iovs.back() );
342  if( Base::tagTimeType()==cond::lumiid ){
343  min = min >> 32;
344  max = max >> 32;
345  }
346  runInfo = Base::dbSession().getRunInfo( min, max );
347  }
348  for( auto iov : iovs ) {
349  cond::Time_t since = std::get<0>(iov);
350  boost::posix_time::ptime time;
351  std::string label("");
352  if( Base::tagTimeType()==cond::lumiid || Base::tagTimeType()==cond::runnumber){
353  unsigned int nlumi = since & 0xFFFFFFFF;
354  if( Base::tagTimeType()==cond::lumiid ) since = since >> 32;
355  label = boost::lexical_cast<std::string>( since );
356  auto it = runInfo.find( since );
357  if ( it == runInfo.end() ){
358  // this should never happen...
359  return false;
360  }
361  time = (*it).start;
362  // add the lumi sections...
363  if( Base::tagTimeType()==cond::lumiid ){
365  label += (" : "+boost::lexical_cast<std::string>( nlumi ) );
366  }
367  } else if ( Base::tagTimeType()==cond::timestamp ){
368  time = cond::time::to_boost( since );
369  label = boost::posix_time::to_simple_string( time );
370  }
371  std::shared_ptr<PayloadType> payload = Base::fetchPayload( std::get<1>(iov) );
372  if( payload.get() ){
373  Y value = getFromPayload( *payload );
374  Base::m_plotData.push_back( std::make_tuple(std::make_tuple( cond::time::from_boost(time),label),value));
375  }
376  }
377  return true;
378  }
379 
380  virtual Y getFromPayload( PayloadType& payload ) = 0;
381 
382  };
383 
384  template<typename PayloadType, typename X, typename Y> class ScatterPlot : public Plot2D<PayloadType,X,Y > {
385  public:
387  // the x axis label will be overwritten by the plot rendering application
388  ScatterPlot( const std::string& title, const std::string& xLabel, const std::string& yLabel ) :
389  Base( "Scatter", title, xLabel , yLabel ){
390  }
391 
392  bool fill( const std::vector<std::tuple<cond::Time_t,cond::Hash> >& iovs ) override {
393  for( auto iov : iovs ) {
394  std::shared_ptr<PayloadType> payload = Base::fetchPayload( std::get<1>(iov) );
395  if( payload.get() ){
396  std::tuple<X,Y> value = getFromPayload( *payload );
397  Base::m_plotData.push_back( value );
398  }
399  }
400  return true;
401  }
402 
403  virtual std::tuple<X,Y> getFromPayload( PayloadType& payload ) = 0;
404 
405  };
406 
407  //
408  template<typename PayloadType> class Histogram1D: public Plot2D<PayloadType,float,float > {
409  public:
411  // naive implementation, essentially provided as an example...
412  Histogram1D( const std::string& title, const std::string& xLabel, size_t nbins, float min, float max ):
413  Base( "Histo1D", title, xLabel , "entries" ),m_nbins(nbins),m_min(min),m_max(max){
414  }
415 
416  //
417  void init(){
418  Base::m_plotData.clear();
419  float binSize = (m_max-m_min)/m_nbins;
420  if( binSize>0 ){
421  m_binSize = binSize;
422  Base::m_plotData.resize( m_nbins );
423  for( size_t i=0;i<m_nbins;i++ ){
424  Base::m_plotData[i] = std::make_tuple( m_min+i*m_binSize, 0 );
425  }
426  }
427  }
428 
429  // to be used to fill the histogram!
430  void fillWithValue( float value, float weight=1 ){
431  // ignoring underflow/overflows ( they can be easily added - the total entries as well )
432  if( Base::m_plotData.size() && (value < m_max) && (value >= m_min) ){
433  size_t ibin = (value-m_min)/m_binSize;
434  std::get<1>(Base::m_plotData[ibin])+=weight;
435  }
436  }
437 
438  // this one can ( and in general should ) be overridden - the implementation should use fillWithValue
439  virtual bool fill( const std::vector<std::tuple<cond::Time_t,cond::Hash> >& iovs ) override {
440  for( auto iov : iovs ) {
441  std::shared_ptr<PayloadType> payload = Base::fetchPayload( std::get<1>(iov) );
442  if( payload.get() ){
443  float value = getFromPayload( *payload );
444  fillWithValue( value );
445  }
446  }
447  return true;
448  }
449 
450  // implement this one if you use the default fill implementation, otherwise ignore it...
451  virtual float getFromPayload( PayloadType& payload ) {
452  return 0;
453  }
454 
455  private:
456  float m_binSize = 0;
457  size_t m_nbins;
458  float m_min;
459  float m_max;
460  };
461 
462  //
463  template<typename PayloadType> class Histogram2D: public Plot3D<PayloadType,float,float,float > {
464  public:
466  // naive implementation, essentially provided as an example...
467  Histogram2D( const std::string& title, const std::string& xLabel, size_t nxbins, float xmin, float xmax,
468  const std::string& yLabel, size_t nybins, float ymin, float ymax ):
469  Base( "Histo2D", title, xLabel , yLabel, "entries" ),m_nxbins( nxbins), m_xmin(xmin),m_xmax(xmax),m_nybins(nybins),m_ymin(ymin),m_ymax(ymax){
470  }
471 
472  //
473  void init(){
474  Base::m_plotData.clear();
475  float xbinSize = (m_xmax-m_xmin)/m_nxbins;
476  float ybinSize = (m_ymax-m_ymin)/m_nybins;
477  if( xbinSize>0 && ybinSize>0){
478  m_xbinSize = xbinSize;
479  m_ybinSize = ybinSize;
480  Base::m_plotData.resize( m_nxbins*m_nybins );
481  for( size_t i=0;i<m_nybins;i++ ){
482  for( size_t j=0;j<m_nxbins;j++ ){
483  Base::m_plotData[i*m_nxbins+j] = std::make_tuple( m_xmin+j*m_xbinSize, m_ymin+i*m_ybinSize, 0 );
484  }
485  }
486  }
487  }
488 
489  // to be used to fill the histogram!
490  void fillWithValue( float xvalue, float yvalue, float weight=1 ){
491  // ignoring underflow/overflows ( they can be easily added - the total entries as well )
492  if( Base::m_plotData.size() && xvalue < m_xmax && xvalue >= m_xmin && yvalue < m_ymax && yvalue >= m_ymin ){
493  size_t ixbin = (xvalue-m_xmin)/m_xbinSize;
494  size_t iybin = (yvalue-m_ymin)/m_ybinSize;
495  std::get<2>(Base::m_plotData[iybin*m_nxbins+ixbin])+=weight;
496  }
497  }
498 
499  // this one can ( and in general should ) be overridden - the implementation should use fillWithValue
500  virtual bool fill( const std::vector<std::tuple<cond::Time_t,cond::Hash> >& iovs ) override {
501  for( auto iov : iovs ) {
502  std::shared_ptr<PayloadType> payload = Base::fetchPayload( std::get<1>(iov) );
503  if( payload.get() ){
504  std::tuple<float,float> value = getFromPayload( *payload );
505  fillWithValue( std::get<0>(value),std::get<1>(value) );
506  }
507  }
508  return true;
509  }
510 
511  // implement this one if you use the default fill implementation, otherwise ignore it...
512  virtual std::tuple<float,float> getFromPayload( PayloadType& payload ) {
513  float x = 0;
514  float y = 0;
515  return std::make_tuple(x,y);
516  }
517 
518  private:
519  size_t m_nxbins;
520  float m_xbinSize = 0;
521  float m_xmin;
522  float m_xmax;
523  float m_ybinSize = 0;
524  size_t m_nybins;
525  float m_ymin;
526  float m_ymax;
527  };
528 
529  }
530 
531 }
532 
533 #endif
534 
size
Write out results.
type
Definition: HCALResponse.h:21
bool fill(const std::vector< std::tuple< cond::Time_t, cond::Hash > > &iovs) override
double seconds()
bool fill(const std::vector< std::tuple< cond::Time_t, cond::Hash > > &iovs) override
bool fill(const std::vector< std::tuple< cond::Time_t, cond::Hash > > &iovs) override
Plot3D< PayloadType, float, float, float > Base
std::vector< std::tuple< X, Y, Z > > m_plotData
Plot2D< PayloadType, unsigned long long, Y > Base
Definition: weight.py:1
static const char *const JSON_FORMAT_VERSION
void fillWithValue(float xvalue, float yvalue, float weight=1)
std::map< std::string, std::string > m
std::vector< std::tuple< X, Y > > m_plotData
#define constexpr
TimeType
Definition: Time.h:21
ScatterPlot(const std::string &title, const std::string &xLabel, const std::string &yLabel)
virtual float getFromPayload(PayloadType &payload)
T x() const
Cartesian x coordinate.
std::string processData(const std::vector< std::tuple< cond::Time_t, cond::Hash > > &iovs) override
payload
payload postfix for testing
unsigned long long Time_t
Definition: Time.h:16
std::string serializeValue(const std::string &entryLabel, const V &value)
Plot2D< PayloadType, X, Y > Base
std::string Hash
Definition: Types.h:45
RunHistoryPlot(const std::string &title, const std::string &yLabel)
Plot2D< PayloadType, float, float > Base
std::shared_ptr< PayloadType > fetchPayload(const cond::Hash &payloadHash)
#define end
Definition: vmac.h:37
std::string serialize(const PlotAnnotations &annotations, const std::vector< std::tuple< X, Y > > &data)
Definition: value.py:1
void fillWithValue(float value, float weight=1)
virtual bool fill(const std::vector< std::tuple< cond::Time_t, cond::Hash > > &iovs) override
T min(T a, T b)
Definition: MathUtil.h:58
Time_t from_boost(boost::posix_time::ptime bt)
static const char *const PAYLOAD_TYPE_K
Histogram1D(const std::string &title, const std::string &xLabel, size_t nbins, float min, float max)
const unsigned int SECONDS_PER_LUMI(23)
Plot3D(const std::string &type, const std::string &title, const std::string xLabel, const std::string &yLabel, const std::string &zLabel)
std::string processData(const std::vector< std::tuple< cond::Time_t, cond::Hash > > &iovs) override
std::shared_ptr< PayloadType > fetchPayload(const cond::Hash &payloadHash)
Plot2D< PayloadType, std::tuple< float, std::string >, Y > Base
TimeHistoryPlot(const std::string &title, const std::string &yLabel)
Iterator find(Time_t target) const
virtual std::tuple< float, float > getFromPayload(PayloadType &payload)
HistoryPlot(const std::string &title, const std::string &yLabel)
std::string serializeAnnotations(const PlotAnnotations &annotations)
Histogram2D(const std::string &title, const std::string &xLabel, size_t nxbins, float xmin, float xmax, const std::string &yLabel, size_t nybins, float ymin, float ymax)
Definition: plugin.cc:24
#define begin
Definition: vmac.h:30
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
cond::persistency::Session m_dbSession
double a
Definition: hdecay.h:121
bool fill(const std::vector< std::tuple< cond::Time_t, cond::Hash > > &iovs) override
std::shared_ptr< PayloadType > fetchPayload(const cond::Hash &payloadHash)
Plot2D< PayloadType, std::tuple< unsigned long long, std::string >, Y > Base
Plot2D(const std::string &type, const std::string &title, const std::string xLabel, const std::string &yLabel)
boost::posix_time::ptime to_boost(Time_t iValue)
virtual bool fill(const std::vector< std::tuple< cond::Time_t, cond::Hash > > &iovs) override