Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TpotMonDraw.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TpotMonDraw.cc
1 #include "TpotMonDraw.h"
2 #include "TpotMonDefs.h"
3 
4 #include <onlmon/OnlMonClient.h>
5 #include <onlmon/OnlMonDB.h>
6 
7 #include <TAxis.h> // for TAxis
8 #include <TCanvas.h>
9 #include <TDatime.h>
10 #include <TGraphErrors.h>
11 #include <TH1.h>
12 #include <TLine.h>
13 #include <TPad.h>
14 #include <TROOT.h>
15 #include <TSystem.h>
16 #include <TText.h>
17 
18 #include <cstring> // for memset
19 #include <ctime>
20 #include <fstream>
21 #include <iostream> // for operator<<, basic_ostream, basic_os...
22 #include <sstream>
23 #include <vector> // for vector
24 
25 namespace
26 {
28  class CanvasEditor
29  {
30  public:
31  CanvasEditor( TCanvas* cv ):m_cv(cv)
32  { if( m_cv ) m_cv->SetEditable(true); }
33 
34  ~CanvasEditor()
35  // {}
36  { if( m_cv ) m_cv->SetEditable(false); }
37 
38  private:
39  TCanvas* m_cv = nullptr;
40  };
41 
42  TPad* create_transparent_pad( const std::string& name )
43  {
44  auto transparent = new TPad( (name+"_transparent").c_str(), "", 0, 0, 1, 1);
45  transparent->SetFillStyle(4000);
46  transparent->Draw();
47  return transparent;
48  };
49 
50  TPad* get_transparent_pad( TPad* parent, const std::string& name, bool clear = true)
51  {
52  if( !parent ) return nullptr;
53  const std::string transparent_name = name+"_transparent";
54  auto out = dynamic_cast<TPad*>( parent->FindObject( transparent_name.c_str() ) );
55 
56  if( !out ) std::cout << "get_transparent_pad - " << transparent_name << " not found" << std::endl;
57  if( out && clear ) out->Clear("D");
58  return out;
59 
60  }
61 
62  // draw an vertical line that extends automatically from both sides of a canvas
63  [[maybe_unused]] TLine* vertical_line( TVirtualPad* pad, Double_t x )
64  {
65  Double_t yMin = pad->GetUymin();
66  Double_t yMax = pad->GetUymax();
67 
68  if( pad->GetLogy() )
69  {
70  yMin = std::pow( 10, yMin );
71  yMax = std::pow( 10, yMax );
72  }
73 
74  return new TLine( x, yMin, x, yMax );
75  }
76 
77  // draw an horizontal line that extends automatically from both sides of a canvas
78  [[maybe_unused]] TLine* horizontal_line( TVirtualPad* pad, Double_t y )
79  {
80  Double_t xMin = pad->GetUxmin();
81  Double_t xMax = pad->GetUxmax();
82 
83  if( pad->GetLogx() )
84  {
85  xMin = std::pow( 10, xMin );
86  xMax = std::pow( 10, xMax );
87  }
88 
89  return new TLine( xMin, y, xMax, y );
90  }
91 
92  // divide canvas, adjusting canvas positions to leave room for a banner at the top
93  void divide_canvas( TCanvas* cv, int ncol, int nrow )
94  {
95  static constexpr double max_height = 0.94;
96 
97  cv->Divide( ncol, nrow );
98  for( int i = 0; i < ncol*nrow; ++i )
99  {
100  auto pad = cv->GetPad( i+1 );
101  int col = i%ncol;
102  int row = i/ncol;
103  const double xmin = double(col)/ncol;
104  const double xmax = double(col+1)/ncol;
105 
106  const double ymin = max_height*(1. - double(row+1)/nrow);
107  const double ymax = max_height*(1. - double(row)/nrow);
108  pad->SetPad( xmin, ymin, xmax, ymax );
109  }
110 
111  }
112 }
113 
114 //__________________________________________________________________________________
116  : OnlMonDraw(name)
117 {
118  // setup default filename for reference histograms
119  const auto tpotcalibref = getenv("TPOTCALIBREF");
120  if( tpotcalibref )
121  {
122  m_ref_histograms_filename = std::string(tpotcalibref) + "/" + "Run_00000-TPOTMON_0.root";
123  std::cout << "TpotMon::TpotMon - reading reference histograms from: " << m_ref_histograms_filename << std::endl;
124  m_ref_histograms_tfile.reset( TFile::Open( m_ref_histograms_filename.c_str(), "READ" ) );
125  } else {
126  m_ref_histograms_filename = "Run_00000-TPOTMON_0.root";
127  std::cout << "TpotMon::TpotMon - TPOTCALIBREF environment variable not set. Reading reference histograms from: " << m_ref_histograms_filename << std::endl;
128  m_ref_histograms_tfile.reset( TFile::Open( m_ref_histograms_filename.c_str(), "READ" ) );
129  }
130 
131  // this TimeOffsetTicks is neccessary to get the time axis right
132  TDatime T0(2003, 01, 01, 00, 00, 00);
133  TimeOffsetTicks = T0.Convert();
134  dbvars.reset( new OnlMonDB(ThisName) );
135 
136  // initialize local list of detector names
137  for( const auto& fee_id:m_mapping.get_fee_id_list() )
138  { m_detnames_sphenix.push_back( m_mapping.get_detname_sphenix( fee_id ) ); }
139 
140 }
141 
142 //__________________________________________________________________________________
144 { return 0; }
145 
146 //__________________________________________________________________________________
148 {
149  if( !pad )
150  {
151  if( Verbosity() ) std::cout << "TpotMonDraw::DrawDeadServer - invalid pad" << std::endl;
152  return 0;
153  } else {
154  pad->SetPad(0,0,1,1);
155  return OnlMonDraw::DrawDeadServer( pad );
156  }
157 }
158 
159 //__________________________________________________________________________________
160 void TpotMonDraw::draw_time( TPad* pad )
161 {
162  if( !pad )
163  {
164  if( Verbosity() ) std::cout << "TpotMonDraw::draw_time - invalid pad" << std::endl;
165  return;
166  }
167 
168  pad->SetPad( 0, 0.94, 1, 1 );
169  pad->Clear();
170  TText PrintRun;
171  PrintRun.SetTextFont(62);
172  PrintRun.SetTextSize(0.6);
173  PrintRun.SetNDC(); // set to normalized coordinates
174  PrintRun.SetTextAlign(23); // center/top alignment
175 
176  std::ostringstream runnostream;
177  auto cl = OnlMonClient::instance();
178  time_t evttime = cl->EventTime("CURRENT");
179 
180  runnostream
181  << ThisName << " Run " << cl->RunNumber()
182  << ", Time: " << ctime(&evttime);
183 
184  pad->cd();
185  PrintRun.DrawText(0.5, 0.5, runnostream.str().c_str());
186 }
187 
188 //__________________________________________________________________________________
189 TCanvas* TpotMonDraw::get_canvas(const std::string& name, bool clear )
190 {
191  auto cv = dynamic_cast<TCanvas*>( gROOT->FindObject( name.c_str() ) );
192  if( !cv ) cv = create_canvas( name );
193  if( cv && clear ) cv->Clear("D");
194  return cv;
195 }
196 
197 //__________________________________________________________________________________
199 {
200 
201  if( Verbosity() )
202  { std::cout << "TpotMonDraw::create_canvas - name: " << name << std::endl; }
203 
205  int xsize = cl->GetDisplaySizeX();
206  int ysize = cl->GetDisplaySizeY();
207 
208  if (name == "TPOT_counters")
209  {
210 
211  // xpos (-1) negative: do not draw menu bar
212  auto cv = new TCanvas(name.c_str(), "TPOT event counters", -1, 0, xsize / 2, ysize);
213  gSystem->ProcessEvents();
214  divide_canvas( cv, 1, 1 );
215  create_transparent_pad(name);
216  cv->SetEditable(false);
217  m_canvas.push_back( cv );
218  return cv;
219  } else if (name == "TPOT_detector_occupancy") {
220 
221  // xpos (-1) negative: do not draw menu bar
222  auto cv = new TCanvas(name.c_str(), "TPOT detector occupancy", -1, 0, xsize / 2, ysize);
223  gSystem->ProcessEvents();
224  divide_canvas( cv, 1, 2 );
225  create_transparent_pad(name);
226  cv->SetEditable(false);
227  m_canvas.push_back( cv );
228  return cv;
229 
230  } else if (name == "TPOT_resist_occupancy") {
231 
232  // xpos (-1) negative: do not draw menu bar
233  auto cv = new TCanvas(name.c_str(), "TPOT resist occupancy", -1, 0, xsize / 2, ysize);
234  gSystem->ProcessEvents();
235  divide_canvas( cv, 1, 2 );
236  create_transparent_pad(name);
237  cv->SetEditable(false);
238  m_canvas.push_back( cv );
239  return cv;
240 
241  } else if (name == "TPOT_adc_vs_sample") {
242 
243  auto cv = new TCanvas(name.c_str(), "TpotMon adc vs sample", -1, 0, xsize / 2, ysize);
244  gSystem->ProcessEvents();
245  divide_canvas( cv, 4, 4 );
246  create_transparent_pad(name);
247  for( int i = 0; i < 16; ++i )
248  {
249  cv->GetPad(i+1)->SetLeftMargin(0.15);
250  cv->GetPad(i+1)->SetRightMargin(0.02);
251  }
252  cv->SetEditable(false);
253  m_canvas.push_back( cv );
254  return cv;
255 
256  } else if (name == "TPOT_counts_vs_sample") {
257 
258  auto cv = new TCanvas(name.c_str(), "TpotMon counts vs sample", -1, 0, xsize / 2, ysize);
259  gSystem->ProcessEvents();
260  divide_canvas( cv, 4, 4 );
261  create_transparent_pad(name);
262  for( int i = 0; i < 16; ++i )
263  {
264  auto&& pad = cv->GetPad(i+1);
265  pad->SetLeftMargin(0.15);
266  pad->SetRightMargin(0.02);
267  }
268 
269  cv->SetEditable(false);
270  m_canvas.push_back( cv );
271  return cv;
272 
273  } else if (name == "TPOT_hit_charge") {
274 
275  auto cv = new TCanvas(name.c_str(), "TpotMon hit charge", -1, 0, xsize / 2, ysize);
276  gSystem->ProcessEvents();
277  divide_canvas( cv, 4, 4 );
278  create_transparent_pad(name);
279  cv->SetEditable(false);
280  m_canvas.push_back( cv );
281  return cv;
282 
283  } else if (name == "TPOT_hit_multiplicity") {
284 
285  auto cv = new TCanvas(name.c_str(), "TpotMon hit multiplicity", -1, 0, xsize / 2, ysize);
286  gSystem->ProcessEvents();
287  divide_canvas( cv, 4, 4 );
288  create_transparent_pad(name);
289  cv->SetEditable(false);
290  m_canvas.push_back( cv );
291  return cv;
292 
293  } else if (name == "TPOT_hit_vs_channel") {
294 
295  auto cv = new TCanvas(name.c_str(), "TpotMon hit vs channel", -1, 0, xsize / 2, ysize);
296  gSystem->ProcessEvents();
297  divide_canvas( cv, 4, 4 );
298  create_transparent_pad(name);
299  cv->SetEditable(false);
300  m_canvas.push_back( cv );
301  return cv;
302 
303  }
304  return nullptr;
305 }
306 
307 //_______________________________________________________________________________
309 {
310  if( Verbosity() )
311  { std::cout << "TpotMonDraw::Draw - what: " << what << std::endl; }
312 
313  int iret = 0;
314  int idraw = 0;
315 
316  {
317  // get counters
318  const auto m_counters = get_histogram( "m_counters");
319  if( m_counters && Verbosity() )
320  {
321  const int events = m_counters->GetBinContent( TpotMonDefs::kEventCounter );
322  const int valid_events = m_counters->GetBinContent( TpotMonDefs::kValidEventCounter );
323  std::cout << "TpotMonDraw::Draw - events: " << events << " valid events: " << valid_events << std::endl;
324  }
325  }
326 
327  if( what == "ALL" || what == "TPOT_counters" )
328  {
329  iret += draw_counters();
330  ++idraw;
331  }
332 
333  if( what == "ALL" || what == "TPOT_detector_occupancy" )
334  {
335  iret += draw_detector_occupancy();
336  ++idraw;
337  }
338 
339  if( what == "ALL" || what == "TPOT_resist_occupancy" )
340  {
341  iret += draw_resist_occupancy();
342  ++idraw;
343  }
344 
345  if (what == "ALL" || what == "TPOT_adc_vs_sample")
346  {
347  iret += draw_array("TPOT_adc_vs_sample", get_histograms( "m_adc_sample" ), DrawOptions::Colz );
348  auto cv = get_canvas("TPOT_adc_vs_sample");
349  if( cv )
350  {
351  CanvasEditor cv_edit(cv);
352  cv->Update();
353  for( int i = 0; i < 16; ++i )
354  {
355  // draw vertical lines that match sample window
356  auto&& pad = cv->GetPad(i+1);
357  pad->cd();
358  for( const auto line:{vertical_line( pad, m_sample_window_signal.first ), vertical_line( pad, m_sample_window_signal.second ) } )
359  {
360  line->SetLineStyle(2);
361  line->SetLineColor(2);
362  line->SetLineWidth(2);
363  line->Draw();
364  }
365  }
366  }
367  ++idraw;
368  }
369 
370  if (what == "ALL" || what == "TPOT_counts_vs_sample")
371  {
372  iret += draw_array("TPOT_counts_vs_sample", get_histograms( "m_counts_sample" ), get_ref_histograms_scaled( "m_counts_sample" ) );
373  auto cv = get_canvas("TPOT_counts_vs_sample");
374  if( cv )
375  {
376  std::cout << "TpotMonDraw::Draw - draw vertical lines" << std::endl;
377  CanvasEditor cv_edit(cv);
378  cv->Update();
379  for( int i = 0; i < 16; ++i )
380  {
381  // draw vertical lines that match sample window
382  auto&& pad = cv->GetPad(i+1);
383  pad->cd();
384  for( const auto line:{vertical_line( pad, m_sample_window_signal.first ), vertical_line( pad, m_sample_window_signal.second ) } )
385  {
386  line->SetLineStyle(2);
387  line->SetLineColor(2);
388  line->SetLineWidth(2);
389  line->Draw();
390  }
391  }
392  }
393  ++idraw;
394  }
395 
396  if (what == "ALL" || what == "TPOT_hit_charge")
397  {
398  iret += draw_array("TPOT_hit_charge", get_histograms( "m_hit_charge" ), get_ref_histograms_scaled( "m_hit_charge" ), DrawOptions::Logy );
399  ++idraw;
400  }
401 
402  if (what == "ALL" || what == "TPOT_hit_multiplicity")
403  {
404  iret += draw_array("TPOT_hit_multiplicity", get_histograms( "m_hit_multiplicity" ), get_ref_histograms_scaled( "m_hit_multiplicity" ), DrawOptions::Logy );
405  ++idraw;
406  }
407 
408  if (what == "ALL" || what == "TPOT_hit_vs_channel")
409  {
410  iret += draw_array("TPOT_hit_vs_channel", get_histograms( "m_hit_vs_channel" ), get_ref_histograms_scaled( "m_hit_vs_channel" ) );
411  auto cv = get_canvas("TPOT_hit_vs_channel");
412  if( cv )
413  {
414  CanvasEditor cv_edit(cv);
415  cv->Update();
416  for( int i = 0; i < 16; ++i )
417  {
418  // draw vertical lines that match sample window
419  auto&& pad = cv->GetPad(i+1);
420  pad->cd();
421  for( const int& channel:{64, 128, 196} )
422  {
423  const auto line = vertical_line( pad, channel );
424  line->SetLineStyle(2);
425  line->SetLineColor(1);
426  line->SetLineWidth(1);
427  line->Draw();
428  }
429  }
430  }
431  ++idraw;
432  }
433 
434  if (!idraw)
435  {
436  std::cout << "TpotMonDraw::Draw - Unimplemented Drawing option: " << what << std::endl;
437  iret = -1;
438  }
439  return iret;
440 }
441 
442 //_______________________________________________________________________________
444 {
445  auto cl = OnlMonClient::instance();
446  const int iret = Draw(what);
447  if (iret) return iret;
448 
449  for( std::size_t i =0; i < m_canvas.size(); ++i )
450  {
451  const auto& cv = m_canvas[i];
452  if( cv )
453  {
454  std::string filename = ThisName + "_" + std::to_string(i+1) + "_" +
455  std::to_string(cl->RunNumber()) + "." + type;
456  cl->CanvasToPng(cv, filename);
457  }
458  }
459 
460  return 0;
461 }
462 
463 //__________________________________________________________________________________
465 {
466  const int iret = Draw(what);
467  if (iret) return iret;
468 
469  auto cl = OnlMonClient::instance();
470 
471  // Register the 1st canvas png file to the menu and produces the png file.
472  for( std::size_t i =0; i < m_canvas.size(); ++i )
473  {
474  const auto& cv = m_canvas[i];
475  if( cv )
476  {
477  const auto pngfile = cl->htmlRegisterPage(*this, cv->GetName(), Form("%lu", i+1), "png");
478  cl->CanvasToPng(cv, pngfile);
479  }
480  }
481 
482  // log
483  {
484  const std::string logfile = cl->htmlRegisterPage(*this, "EXPERTS/Log", "log", "html");
485  std::ofstream out(logfile.c_str());
486  out
487  << "<HTML><HEAD><TITLE>Log file for run " << cl->RunNumber()
488  << "</TITLE></HEAD>"
489  << std::endl
490  << "<P>Some log file output would go here."
491  << std::endl;
492  out.close();
493  }
494 
495  // status
496  {
497  const std::string status = cl->htmlRegisterPage(*this, "EXPERTS/Status", "status", "html");
498  std::ofstream out(status.c_str());
499  out
500  << "<HTML><HEAD><TITLE>Status file for run " << cl->RunNumber()
501  << "</TITLE></HEAD>"
502  << std::endl
503  << "<P>Some status output would go here."
504  << std::endl;
505  out.close();
506  cl->SaveLogFile(*this);
507  }
508 
509  return 0;
510 }
511 
512 //__________________________________________________________________________________
514 {
515 
516  if( Verbosity() ) std::cout << "TpotMonDraw::draw_counters" << std::endl;
517 
518  // get histograms
519  auto m_counters = get_histogram( "m_counters");
520  std::unique_ptr<TH1> m_counters_ref( normalize( get_ref_histogram( "m_counters" ), get_ref_scale_factor() ) );
521 
522  auto cv = get_canvas("TPOT_counters");
523  auto transparent = get_transparent_pad( cv, "TPOT_counters");
524  if( !cv )
525  {
526  if( Verbosity() ) std::cout << "TpotMonDraw::draw_counters - no canvas" << std::endl;
527  return -1;
528  }
529 
530  CanvasEditor cv_edit(cv);
531 
532  if( m_counters )
533  {
534  cv->cd(1);
535  gPad->SetLeftMargin( 0.07 );
536  gPad->SetRightMargin( 0.15 );
537  m_counters->SetFillStyle(1001);
538  m_counters->SetFillColor(kYellow );
539  m_counters->DrawCopy( "h" );
540 
541  if( m_counters_ref )
542  {
543  m_counters_ref->SetLineColor(2);
544  m_counters_ref->DrawCopy( "hist same" );
545  }
546 
547  draw_time(transparent);
548  return 0;
549  } else {
550 
551  DrawDeadServer(transparent);
552  return -1;
553  }
554 }
555 
556 //__________________________________________________________________________________
558 {
559 
560  if( Verbosity() ) std::cout << "TpotMonDraw::draw_detector_occupancy" << std::endl;
561 
562  // get histograms
563  auto m_detector_occupancy_phi = get_histogram( "m_detector_occupancy_phi");
564  auto m_detector_occupancy_z = get_histogram( "m_detector_occupancy_z");
565 
566  // turn off stat panel
567  for( const auto& h:{m_detector_occupancy_phi,m_detector_occupancy_z} )
568  { if(h) h->SetStats(0); }
569 
570  auto cv = get_canvas("TPOT_detector_occupancy");
571  auto transparent = get_transparent_pad( cv, "TPOT_detector_occupancy");
572  if( !cv )
573  {
574  if( Verbosity() ) std::cout << "TpotMonDraw::draw_detector_occupancy - no canvas" << std::endl;
575  return -1;
576  }
577 
578  CanvasEditor cv_edit(cv);
579 
580  if( m_detector_occupancy_phi && m_detector_occupancy_z )
581  {
582  cv->cd(1);
583  gPad->SetLeftMargin( 0.07 );
584  gPad->SetRightMargin( 0.15 );
585  m_detector_occupancy_z->DrawCopy( "colz" );
586  draw_detnames_sphenix( "Z" );
587 
588  cv->cd(2);
589  gPad->SetLeftMargin( 0.07 );
590  gPad->SetRightMargin( 0.15 );
591  m_detector_occupancy_phi->DrawCopy( "colz" );
592  draw_detnames_sphenix( "P" );
593 
594  draw_time(transparent);
595  return 0;
596 
597  } else {
598 
599  DrawDeadServer(transparent);
600  return -1;
601 
602  }
603 }
604 
605 //__________________________________________________________________________________
607 {
608 
609  if( Verbosity() ) std::cout << "TpotMonDraw::draw_resist_occupancy" << std::endl;
610 
611  // get histograms
612  auto m_resist_occupancy_phi = get_histogram( "m_resist_occupancy_phi");
613  auto m_resist_occupancy_z = get_histogram( "m_resist_occupancy_z");
614 
615  // turn off stat panel
616  for( const auto& h:{m_resist_occupancy_phi,m_resist_occupancy_z} )
617  { if(h) h->SetStats(0); }
618 
619  auto cv = get_canvas("TPOT_resist_occupancy");
620  auto transparent = get_transparent_pad( cv, "TPOT_resist_occupancy");
621  if( !cv )
622  {
623  if( Verbosity() ) std::cout << "TpotMonDraw::draw_resist_occupancy - no canvas" << std::endl;
624  return -1;
625  }
626 
627  CanvasEditor cv_edit(cv);
628 
629  if( m_resist_occupancy_phi && m_resist_occupancy_z )
630  {
631  cv->cd(1);
632  gPad->SetLeftMargin( 0.07 );
633  gPad->SetRightMargin( 0.15 );
634  m_resist_occupancy_z->DrawCopy( "colz" );
635  draw_detnames_sphenix( "Z" );
636 
637  cv->cd(2);
638  gPad->SetLeftMargin( 0.07 );
639  gPad->SetRightMargin( 0.15 );
640  m_resist_occupancy_phi->DrawCopy( "colz" );
641  draw_detnames_sphenix( "P" );
642 
643  draw_time(transparent);
644  return 0;
645 
646  } else {
647  DrawDeadServer(transparent);
648  return -1;
649  }
650 }
651 
652 //__________________________________________________________________________________
654 {
655  gPad->Update();
656  for( size_t i = 0; i < m_geometry.get_ntiles(); ++i )
657  {
658  const auto name = m_geometry.get_detname_sphenix(i)+suffix;
659  const auto [x,y] = m_geometry.get_tile_center(i);
660  auto text = new TText();
661  text->DrawText( x-0.8*m_geometry.m_tile_length/2, y-0.8*m_geometry.m_tile_width/2, name.c_str() );
662  text->Draw();
663  }
664 
665 }
666 
667 //__________________________________________________________________________________
668 TH1* TpotMonDraw::get_histogram( const std::string& name ) const
669 {
670  auto cl = OnlMonClient::instance();
671  return cl->getHisto("TPOTMON_0", name );
672 }
673 
674 //__________________________________________________________________________________
676 {
677  histogram_array_t out{{nullptr}};
678  for( size_t i=0; i<m_detnames_sphenix.size(); ++i)
679  {
680  const auto& detector_name=m_detnames_sphenix[i];
681  const auto hname = name + "_" + detector_name;
682  out[i] = get_histogram( hname );
683  if( Verbosity() )
684  { std::cout << "TpotMonDraw::get_histograms - " << hname << (out[i]?" found":" not found" ) << std::endl; }
685  }
686 
687  return out;
688 }
689 
690 //__________________________________________________________________________________
692 { return m_ref_histograms_tfile ? static_cast<TH1*>( m_ref_histograms_tfile->Get( name.c_str() ) ):nullptr; }
693 
694 //__________________________________________________________________________________
696 {
697  histogram_array_t out{{nullptr}};
698  for( size_t i=0; i<m_detnames_sphenix.size(); ++i)
699  {
700  const auto& detector_name=m_detnames_sphenix[i];
701  const auto hname = name + "_" + detector_name;
702  out[i] = get_ref_histogram( hname );
703  if( Verbosity() )
704  { std::cout << "TpotMonDraw::get_ref_histograms - " << hname << (out[i]?" found":" not found" ) << std::endl; }
705  }
706 
707  return out;
708 }
709 
710 //__________________________________________________________________________________
712 {
714  histogram_array_t out{{nullptr}};
715 
716  const double scale = get_ref_scale_factor();
717  for( size_t i=0; i<source.size(); ++i)
718  { if( source[i] ) out[i]=normalize( source[i], scale ); }
719 
720  return out;
721 }
722 
723 //__________________________________________________________________________________
725 {
726  if( !m_ref_histograms_tfile ) return 0;
727  const auto m_counters = get_histogram( "m_counters");
728  const auto m_counters_ref = get_ref_histogram( "m_counters");
729  if( !( m_counters && m_counters_ref ) ) return 0;
730 
731  const double full_events = m_counters->GetBinContent( TpotMonDefs::kFullEventCounter );
732  const double full_events_ref = m_counters_ref->GetBinContent( TpotMonDefs::kFullEventCounter );
733  return full_events_ref > 0 ? full_events/full_events_ref : 0;
734 }
735 
736 //__________________________________________________________________________________
737 TH1* TpotMonDraw::normalize( TH1* source, double scale ) const
738 {
739  if( !source ) return nullptr;
740  auto destination = static_cast<TH1*>( source->Clone() );
741  destination->SetName( TString( source->GetName() )+"_scaled" );
742  destination->Scale( scale );
743  return destination;
744 }
745 
746 //__________________________________________________________________________________
747 int TpotMonDraw::draw_array( const std::string& name, const TpotMonDraw::histogram_array_t& histograms, const TpotMonDraw::histogram_array_t& ref_histograms, unsigned int options )
748 {
749  if( Verbosity() ) std::cout << "TpotMonDraw::draw_array - name: " << name << std::endl;
750 
751  auto cv = get_canvas(name);
752  auto transparent = get_transparent_pad( cv, name);
753  if( !cv ) return -1;
754 
755  bool drawn = false;
756  CanvasEditor cv_edit(cv);
757  for( size_t i = 0; i < histograms.size(); ++i )
758  {
759  if( histograms[i] )
760  {
761  cv->cd(i+1);
762  if( options&DrawOptions::Colz ) histograms[i]->DrawCopy( "col" );
763  else {
764 
765  histograms[i]->SetFillStyle(1001);
766  histograms[i]->SetFillColor(kYellow );
767  histograms[i]->DrawCopy( "h" );
768  histograms[i]->DrawCopy();
769 
770  }
771 
772  // also draw reference
773  if( ref_histograms[i] )
774  {
775  ref_histograms[i]->SetLineColor(2);
776  ref_histograms[i]->Draw("hist same" );
777  }
778 
779  gPad->SetBottomMargin(0.12);
780  if( options&DrawOptions::Logx ) gPad->SetLogx( true );
781  if( options&DrawOptions::Logy && histograms[i]->GetEntries() > 0 ) gPad->SetLogy( true );
782  if( options&DrawOptions::Logz ) gPad->SetLogz( true );
783  drawn = true;
784  }
785  }
786 
787  if( drawn )
788  {
789  draw_time(transparent);
790  return 0;
791  } else {
792  DrawDeadServer(transparent);
793  return -1;
794  }
795 
796  // need to delete reference histograms to avoid leak
797  for( auto h:ref_histograms ) { delete h; }
798 
799 }