File indexing completed on 2025-08-03 08:21:08
0001 #include "TpotMonDraw.h"
0002 #include "TpotMonDefs.h"
0003
0004 #include <onlmon/OnlMonClient.h>
0005 #include <onlmon/OnlMonDB.h>
0006
0007 #include <micromegas/MicromegasCalibrationData.h>
0008
0009 #include <TAxis.h> // for TAxis
0010 #include <TCanvas.h>
0011 #include <TDatime.h>
0012 #include <TH1.h>
0013 #include <TH2Poly.h>
0014 #include <TLine.h>
0015 #include <TLatex.h>
0016 #include <TPad.h>
0017 #include <TPaveText.h>
0018 #include <TROOT.h>
0019 #include <TSystem.h>
0020 #include <TText.h>
0021
0022 #include <cstring> // for memset
0023 #include <ctime>
0024 #include <fstream>
0025 #include <iostream> // for operator<<, basic_ostream, basic_os...
0026 #include <sstream>
0027 #include <vector> // for vector
0028
0029 namespace
0030 {
0031
0032 class CanvasEditor
0033 {
0034 public:
0035 CanvasEditor( TCanvas* cv ):m_cv(cv)
0036 { if( m_cv ) m_cv->SetEditable(true); }
0037
0038 ~CanvasEditor()
0039
0040 { if( m_cv ) m_cv->SetEditable(false); }
0041
0042 private:
0043 TCanvas* m_cv = nullptr;
0044 };
0045
0046 TPad* create_transparent_pad( const std::string& name )
0047 {
0048 auto transparent = new TPad( (name+"_transparent").c_str(), "", 0, 0, 1, 1);
0049 transparent->SetFillStyle(4000);
0050 transparent->Draw();
0051 return transparent;
0052 };
0053
0054 TPad* get_transparent_pad( TPad* parent, const std::string& name, bool clear = true)
0055 {
0056 if( !parent ) return nullptr;
0057 const std::string transparent_name = name+"_transparent";
0058 auto out = dynamic_cast<TPad*>( parent->FindObject( transparent_name.c_str() ) );
0059
0060 if( !out ) std::cout << "get_transparent_pad - " << transparent_name << " not found" << std::endl;
0061 if( out && clear ) out->Clear("D");
0062 return out;
0063
0064 }
0065
0066
0067 [[maybe_unused]] TLine* vertical_line( TVirtualPad* pad, Double_t x )
0068 {
0069 Double_t yMin = pad->GetUymin();
0070 Double_t yMax = pad->GetUymax();
0071
0072 if( pad->GetLogy() )
0073 {
0074 yMin = std::pow( 10, yMin );
0075 yMax = std::pow( 10, yMax );
0076 }
0077
0078 return new TLine( x, yMin, x, yMax );
0079 }
0080
0081
0082 [[maybe_unused]] TLine* horizontal_line( TVirtualPad* pad, Double_t y )
0083 {
0084 Double_t xMin = pad->GetUxmin();
0085 Double_t xMax = pad->GetUxmax();
0086
0087 if( pad->GetLogx() )
0088 {
0089 xMin = std::pow( 10, xMin );
0090 xMax = std::pow( 10, xMax );
0091 }
0092
0093 return new TLine( xMin, y, xMax, y );
0094 }
0095
0096
0097 void draw_text( Double_t x_ndc, Double_t y_ndc, const TString& value, double text_size = 0.1 )
0098 {
0099 TLatex text;
0100 text.SetNDC( true );
0101 text.SetTextColor(1);
0102 text.SetTextSize(text_size);
0103 text.DrawLatex( x_ndc, y_ndc, value );
0104 }
0105
0106 void mask_scoz( double xmin, double ymin, double xmax, double ymax )
0107 {
0108 auto text = new TPaveText(xmin, ymin, xmax, ymax, "NDC" );
0109 text->SetFillColor(0);
0110 text->SetFillStyle(1001);
0111 text->SetBorderSize(1);
0112 text->SetTextAlign(11);
0113 text->AddText( " Ignore " );
0114 text->Draw();
0115 }
0116
0117
0118 void divide_canvas( TCanvas* cv, int ncol, int nrow )
0119 {
0120 static constexpr double max_height = 0.94;
0121
0122 cv->Divide( ncol, nrow );
0123 for( int i = 0; i < ncol*nrow; ++i )
0124 {
0125 auto pad = cv->GetPad( i+1 );
0126 int col = i%ncol;
0127 int row = i/ncol;
0128 const double xmin = double(col)/ncol;
0129 const double xmax = double(col+1)/ncol;
0130
0131 const double ymin = max_height*(1. - double(row+1)/nrow);
0132 const double ymax = max_height*(1. - double(row)/nrow);
0133 pad->SetPad( xmin, ymin, xmax, ymax );
0134 }
0135 }
0136
0137
0138 void hide_margins( TCanvas* cv, const double left_margin = 0.15, const double bottom_margin = 0.17 )
0139 {
0140 static constexpr double max_height = 0.94;
0141 const double height = 1./(4.+bottom_margin);
0142 const double width = 1./(4.+left_margin);
0143 for( int row = 0; row < 4; ++row )
0144 {
0145 double ymin = row < 3 ? max_height*(1.-double(row+1)*height):0;
0146 double ymax = max_height*(1.-double(row)*height);
0147
0148 for( int column = 0; column < 4; ++column )
0149 {
0150 double xmin = column == 0 ? 0:width*(column+left_margin);
0151 double xmax = width*(column+1+left_margin);
0152
0153 const int i = column + 4*row;
0154 const auto pad = cv->GetPad(i+1);
0155 pad->SetPad( xmin, ymin, xmax, ymax );
0156
0157 pad->SetTopMargin(0);
0158
0159 if(row<3) pad->SetBottomMargin(0);
0160 else pad->SetBottomMargin(bottom_margin);
0161
0162 if(column>0) pad->SetLeftMargin(0);
0163 else pad->SetLeftMargin(left_margin);
0164
0165 if(column<3) pad->SetRightMargin(0);
0166 else pad->SetRightMargin(0.01);
0167
0168
0169 pad->SetTicky();
0170
0171 }
0172 }
0173 }
0174
0175
0176 std::ostream& operator << ( std::ostream&o, const TpotMonDraw::sample_window_t& window )
0177 {
0178 o << "{ " << window.first << ", " << window.second << "}";
0179 return o;
0180 }
0181
0182 }
0183
0184
0185 TpotMonDraw::TpotMonDraw(const std::string &name)
0186 : OnlMonDraw(name)
0187 {
0188
0189
0190 const auto tpotcalib = getenv("TPOTCALIB");
0191 if (!tpotcalib)
0192 {
0193 std::cout << "TpotMon::TpotMon - TPOTCALIB environment variable not set" << std::endl;
0194 exit(1);
0195 }
0196
0197 m_calibration_filename = std::string(tpotcalib) + "/" + "TPOT_Pedestal-000.root";
0198
0199
0200 const auto tpotcalibref = getenv("TPOTCALIBREF");
0201 if( tpotcalibref )
0202 {
0203 m_ref_histograms_filename = std::string(tpotcalibref) + "/" + "Run_00000-TPOTMON_0.root";
0204 std::cout << "TpotMon::TpotMon - reading reference histograms from: " << m_ref_histograms_filename << std::endl;
0205 m_ref_histograms_tfile.reset( TFile::Open( m_ref_histograms_filename.c_str(), "READ" ) );
0206 } else {
0207 m_ref_histograms_filename = "Run_00000-TPOTMON_0.root";
0208 std::cout << "TpotMon::TpotMon - TPOTCALIBREF environment variable not set. Reading reference histograms from: " << m_ref_histograms_filename << std::endl;
0209 m_ref_histograms_tfile.reset( TFile::Open( m_ref_histograms_filename.c_str(), "READ" ) );
0210 }
0211
0212
0213 TDatime T0(2003, 01, 01, 00, 00, 00);
0214 TimeOffsetTicks = T0.Convert();
0215 dbvars.reset( new OnlMonDB(ThisName) );
0216
0217
0218 for( const auto& fee_id:m_mapping.get_fee_id_list() )
0219 { m_detnames_sphenix.push_back( m_mapping.get_detname_sphenix( fee_id ) ); }
0220
0221 }
0222
0223
0224 int TpotMonDraw::Init()
0225 {
0226 if( Verbosity() )
0227 {
0228 std::cout << "TpotMonDraw::Init - m_calibration_filename: " << m_calibration_filename << std::endl;
0229 std::cout << "TpotMonDraw::Init - m_sample_window: " << m_sample_window << std::endl;
0230 std::cout << "TpotMonDraw::Init - m_sample_window_signal: " << m_sample_window_signal << std::endl;
0231 std::cout << "TpotMon::Init - m_n_sigma: " << m_n_sigma << std::endl;
0232 }
0233
0234
0235 if( std::ifstream( m_calibration_filename.c_str() ).good() )
0236 {
0237
0238 MicromegasCalibrationData calibration_data;
0239 calibration_data.read( m_calibration_filename );
0240
0241
0242 const auto fee_id_list = m_mapping.get_fee_id_list();
0243
0244
0245 for( int i = 0; i < MicromegasDefs::m_nfee; ++i)
0246 {
0247
0248
0249 const int fee_id = fee_id_list[i];
0250
0251
0252 m_mean_thresholds[i] = 0;
0253 unsigned int count = 0;
0254
0255
0256 std::string hname = std::string( "h_threshold_" ) + m_detnames_sphenix[i];
0257 auto h = new TH1F( hname.c_str(), hname.c_str(), MicromegasDefs::m_nchannels_fee, 0, MicromegasDefs::m_nchannels_fee );
0258
0259
0260 h->SetMinimum(0);
0261 h->SetMaximum(1024);
0262 h->SetLineColor(2);
0263
0264
0265 m_threshold_histograms[i] = h;
0266
0267
0268 for( int channel = 0; channel < MicromegasDefs::m_nchannels_fee; ++channel )
0269 {
0270
0271
0272 const double pedestal = calibration_data.get_pedestal( fee_id, channel );
0273 const double rms = calibration_data.get_rms( fee_id, channel );
0274 const double threshold = pedestal + m_n_sigma * rms;
0275 const auto strip_index = m_mapping.get_physical_strip(fee_id, channel );
0276
0277
0278 h->SetBinContent( strip_index+1, threshold );
0279
0280 if( rms > 0 )
0281 {
0282
0283 m_mean_thresholds[i] += threshold;
0284 ++count;
0285 }
0286 }
0287
0288 if(count > 0) {m_mean_thresholds[i]/=count;}
0289 }
0290
0291 } else {
0292 std::cout << "TpotMonDraw::Init -"
0293 << " file " << m_calibration_filename << " cannot be opened."
0294 << " No calibration loaded"
0295 << std::endl;
0296 }
0297
0298 return 0;
0299 }
0300
0301
0302 int TpotMonDraw::DrawDeadServer( TPad* pad )
0303 {
0304 if( !pad )
0305 {
0306 if( Verbosity() ) std::cout << "TpotMonDraw::DrawDeadServer - invalid pad" << std::endl;
0307 return 0;
0308 } else {
0309 pad->SetPad(0,0,1,1);
0310 return OnlMonDraw::DrawDeadServer( pad );
0311 }
0312 }
0313
0314
0315 void TpotMonDraw::draw_time( TPad* pad )
0316 {
0317 if( !pad )
0318 {
0319 if( Verbosity() ) std::cout << "TpotMonDraw::draw_time - invalid pad" << std::endl;
0320 return;
0321 }
0322
0323 pad->SetPad( 0, 0.95, 1, 1 );
0324 pad->Clear();
0325 TText PrintRun;
0326 PrintRun.SetTextFont(62);
0327 PrintRun.SetTextSize(0.6);
0328 PrintRun.SetNDC();
0329 PrintRun.SetTextAlign(23);
0330
0331 std::ostringstream runnostream;
0332 auto cl = OnlMonClient::instance();
0333 std::pair<time_t,int> evttime = cl->EventTime("CURRENT");
0334
0335 runnostream
0336 << ThisName << " Run " << cl->RunNumber()
0337 << ", Time: " << ctime(&evttime.first);
0338
0339 pad->cd();
0340 PrintRun.SetTextColor(evttime.second);
0341 PrintRun.DrawText(0.5, 0.5, runnostream.str().c_str());
0342 }
0343
0344
0345 TCanvas* TpotMonDraw::get_canvas(const std::string& name, bool clear )
0346 {
0347 auto cv = dynamic_cast<TCanvas*>( gROOT->FindObject( name.c_str() ) );
0348 if( !cv ) cv = create_canvas( name );
0349 if( cv && clear ) cv->Clear("D");
0350 return cv;
0351 }
0352
0353
0354 TCanvas* TpotMonDraw::create_canvas(const std::string &name)
0355 {
0356
0357 if( Verbosity() )
0358 { std::cout << "TpotMonDraw::create_canvas - name: " << name << std::endl; }
0359
0360 OnlMonClient *cl = OnlMonClient::instance();
0361 int xsize = cl->GetDisplaySizeX();
0362 int ysize = cl->GetDisplaySizeY();
0363
0364 if (name == "TPOT_counters")
0365 {
0366
0367 auto cv = new TCanvas(name.c_str(), "TPOT event counters", -1, 0, xsize / 2, ysize);
0368 gSystem->ProcessEvents();
0369 divide_canvas(cv, 1, 1);
0370 create_transparent_pad(name);
0371 cv->SetEditable(false);
0372 m_canvas.push_back( cv );
0373 return cv;
0374
0375 } else if (name == "TPOT_detector_occupancy") {
0376
0377 auto cv = new TCanvas(name.c_str(), "TPOT detector occupancy", -1, 0, xsize / 2, ysize);
0378 gSystem->ProcessEvents();
0379 divide_canvas(cv, 1, 2);
0380 create_transparent_pad(name);
0381 cv->SetEditable(false);
0382 m_canvas.push_back( cv );
0383 return cv;
0384
0385 } else if (name == "TPOT_resist_occupancy") {
0386
0387 auto cv = new TCanvas(name.c_str(), "TPOT resist occupancy", -1, 0, xsize / 2, ysize);
0388 gSystem->ProcessEvents();
0389 divide_canvas(cv, 1, 2);
0390 create_transparent_pad(name);
0391 cv->SetEditable(false);
0392 m_canvas.push_back( cv );
0393 return cv;
0394
0395 } else if (name == "TPOT_adc_vs_sample") {
0396
0397 auto cv = new TCanvas(name.c_str(), "TpotMon adc vs sample", -1, 0, xsize / 2, ysize);
0398 gSystem->ProcessEvents();
0399 divide_canvas(cv, 4, 4);
0400 hide_margins(cv,0.2);
0401 create_transparent_pad(name);
0402
0403 cv->SetEditable(false);
0404 m_canvas.push_back( cv );
0405 return cv;
0406
0407 } else if (name == "TPOT_sample_vs_channel") {
0408
0409 auto cv = new TCanvas(name.c_str(), "TpotMon sample vs channel", -1, 0, xsize / 2, ysize);
0410 gSystem->ProcessEvents();
0411 divide_canvas(cv, 4, 4);
0412 hide_margins(cv,0.2);
0413 create_transparent_pad(name);
0414
0415 cv->SetEditable(false);
0416 m_canvas.push_back( cv );
0417 return cv;
0418
0419 } else if (name == "TPOT_adc_vs_channel") {
0420
0421 auto cv = new TCanvas(name.c_str(), "TpotMon adc vs channel", -1, 0, xsize / 2, ysize);
0422 gSystem->ProcessEvents();
0423 divide_canvas(cv, 4, 4);
0424 hide_margins(cv,0.2);
0425 create_transparent_pad(name);
0426 cv->SetEditable(false);
0427 m_canvas.push_back( cv );
0428 return cv;
0429
0430 } else if (name == "TPOT_counts_vs_sample") {
0431
0432 auto cv = new TCanvas(name.c_str(), "TpotMon counts vs sample", -1, 0, xsize / 2, ysize);
0433 gSystem->ProcessEvents();
0434 divide_canvas(cv, 4, 4);
0435 hide_margins(cv,0.2);
0436 create_transparent_pad(name);
0437 cv->SetEditable(false);
0438 m_canvas.push_back( cv );
0439 return cv;
0440
0441 } else if (name == "TPOT_hit_charge") {
0442
0443 auto cv = new TCanvas(name.c_str(), "TpotMon hit charge", -1, 0, xsize / 2, ysize);
0444 gSystem->ProcessEvents();
0445 divide_canvas(cv, 4, 4);
0446 hide_margins(cv);
0447 create_transparent_pad(name);
0448 cv->SetEditable(false);
0449 m_canvas.push_back( cv );
0450 return cv;
0451
0452 } else if (name == "TPOT_hit_multiplicity") {
0453
0454 auto cv = new TCanvas(name.c_str(), "TpotMon hit multiplicity", -1, 0, xsize / 2, ysize);
0455 gSystem->ProcessEvents();
0456 divide_canvas(cv, 4, 4);
0457 hide_margins(cv);
0458 create_transparent_pad(name);
0459 cv->SetEditable(false);
0460 m_canvas.push_back( cv );
0461 return cv;
0462
0463 } else if (name == "TPOT_waveform_vs_channel") {
0464
0465 auto cv = new TCanvas(name.c_str(), "TpotMon waveform vs channel", -1, 0, xsize / 2, ysize);
0466 gSystem->ProcessEvents();
0467 divide_canvas(cv, 4, 4);
0468 hide_margins(cv,0.2);
0469 create_transparent_pad(name);
0470 cv->SetEditable(false);
0471 m_canvas.push_back( cv );
0472 return cv;
0473
0474
0475 } else if (name == "TPOT_heartbeat_vs_channel") {
0476
0477 auto cv = new TCanvas(name.c_str(), "TpotMon heartbeat vs channel", -1, 0, xsize / 2, ysize);
0478 gSystem->ProcessEvents();
0479 divide_canvas(cv, 4, 4);
0480 hide_margins(cv,0.2);
0481 create_transparent_pad(name);
0482 cv->SetEditable(false);
0483 m_canvas.push_back( cv );
0484 return cv;
0485
0486 } else if (name == "TPOT_hit_vs_channel") {
0487
0488 auto cv = new TCanvas(name.c_str(), "TpotMon hit vs channel", -1, 0, xsize / 2, ysize);
0489 gSystem->ProcessEvents();
0490 divide_canvas(cv, 4, 4);
0491 hide_margins(cv,0.2);
0492 create_transparent_pad(name);
0493 cv->SetEditable(false);
0494 m_canvas.push_back( cv );
0495 return cv;
0496
0497 } else if (name == "TPOT_server_stats") {
0498
0499 auto cv = new TCanvas(name.c_str(), "TPOT Server Statistics", -1, 0, 2*xsize/3, ysize);
0500 gSystem->ProcessEvents();
0501 create_transparent_pad(name);
0502 cv->SetEditable(false);
0503 m_canvas.push_back( cv );
0504 return cv;
0505
0506 }
0507
0508 return nullptr;
0509 }
0510
0511
0512 int TpotMonDraw::Draw(const std::string &what)
0513 {
0514 if( Verbosity() )
0515 { std::cout << "TpotMonDraw::Draw - what: " << what << std::endl; }
0516
0517 int iret = 0;
0518 int idraw = 0;
0519
0520 {
0521
0522 const auto m_counters = get_histogram( "m_counters");
0523 if( m_counters )
0524 {
0525 m_triggercnt = m_counters->GetBinContent( TpotMonDefs::kTriggerCounter );
0526 m_heartbeatcnt = m_counters->GetBinContent( TpotMonDefs::kHeartBeatCounter );
0527 } else {
0528 m_triggercnt = 0;
0529 m_heartbeatcnt = 0;
0530 }
0531
0532 if( m_counters && Verbosity() )
0533 {
0534 const int events = m_counters->GetBinContent( TpotMonDefs::kEventCounter );
0535 const int valid_events = m_counters->GetBinContent( TpotMonDefs::kValidEventCounter );
0536 std::cout << "TpotMonDraw::Draw - RCDAQ frames: " << events << " valid RCDAQ frames: " << valid_events << std::endl;
0537 }
0538 }
0539
0540 if( what == "ALL" || what == "TPOT_counters" )
0541 {
0542 iret += draw_counters();
0543 ++idraw;
0544 }
0545
0546 if( what == "ALL" || what == "TPOT_detector_occupancy" )
0547 {
0548 iret += draw_detector_occupancy();
0549 ++idraw;
0550 }
0551
0552 if( what == "ALL" || what == "TPOT_resist_occupancy" )
0553 {
0554 iret += draw_resist_occupancy();
0555 ++idraw;
0556 }
0557
0558 if (what == "ALL" || what == "TPOT_adc_vs_sample")
0559 {
0560
0561
0562 auto h_array = get_histograms( "m_adc_sample" );
0563 for( const auto& h:h_array )
0564 {
0565 if( h )
0566 { h->GetXaxis()->SetRangeUser( m_sample_window.first, m_sample_window.second ); }
0567 }
0568
0569 iret += draw_array("TPOT_adc_vs_sample", h_array, DrawOptions::Colz|DrawOptions::Logz );
0570 auto cv = get_canvas("TPOT_adc_vs_sample");
0571 if( cv )
0572 {
0573 CanvasEditor cv_edit(cv);
0574 cv->Update();
0575
0576 for( int i = 0; i < MicromegasDefs::m_nfee; ++i )
0577 {
0578
0579 auto&& pad = cv->GetPad(i+1);
0580 pad->cd();
0581 pad->Update();
0582 for( const auto line:{vertical_line( pad, m_sample_window_signal.first ), vertical_line( pad, m_sample_window_signal.second ) } )
0583 {
0584 line->SetLineStyle(2);
0585 line->SetLineColor(2);
0586 line->SetLineWidth(2);
0587 line->Draw();
0588 }
0589
0590
0591 if( m_mean_thresholds[i] > 0 )
0592 {
0593 auto line = horizontal_line( pad, m_mean_thresholds[i] );
0594 line->SetLineStyle(2);
0595 line->SetLineColor(2);
0596 line->SetLineWidth(2);
0597 line->Draw();
0598 }
0599 }
0600 }
0601 ++idraw;
0602 }
0603
0604 if (what == "ALL" || what == "TPOT_sample_vs_channel")
0605 {
0606 iret += draw_array("TPOT_sample_vs_channel", get_histograms( "m_sample_channel" ), DrawOptions::Colz);
0607 auto cv = get_canvas("TPOT_sample_vs_channel");
0608 if( cv )
0609 {
0610 CanvasEditor cv_edit(cv);
0611 cv->Update();
0612 for( int i = 0; i < MicromegasDefs::m_nfee; ++i )
0613 {
0614 auto&& pad = cv->GetPad(i+1);
0615 pad->cd();
0616
0617
0618 for( const int& channel:{64, 128, 196} )
0619 {
0620 const auto line = vertical_line( pad, channel );
0621 line->SetLineStyle(2);
0622 line->SetLineColor(2);
0623 line->SetLineWidth(1);
0624 line->Draw();
0625 }
0626 }
0627 {
0628
0629 auto&& pad = cv->GetPad(9);
0630 pad->cd();
0631 mask_scoz(0.22,0.02,0.58, 0.98);
0632 }
0633 }
0634 ++idraw;
0635 }
0636
0637 if (what == "ALL" || what == "TPOT_adc_vs_channel")
0638 {
0639 iret += draw_array("TPOT_adc_vs_channel", get_histograms( "m_adc_channel" ), DrawOptions::Colz|DrawOptions::Logz );
0640 auto cv = get_canvas("TPOT_adc_vs_channel");
0641 if( cv )
0642 {
0643 CanvasEditor cv_edit(cv);
0644 cv->Update();
0645 for( int i = 0; i < MicromegasDefs::m_nfee; ++i )
0646 {
0647
0648 auto&& pad = cv->GetPad(i+1);
0649 pad->cd();
0650
0651
0652 if( m_threshold_histograms[i] )
0653 { m_threshold_histograms[i]->Draw("h same"); }
0654
0655
0656 for( const int& channel:{64, 128, 196} )
0657 {
0658 const auto line = vertical_line( pad, channel );
0659 line->SetLineStyle(2);
0660 line->SetLineColor(1);
0661 line->SetLineWidth(1);
0662 line->Draw();
0663 }
0664 }
0665
0666 {
0667
0668 auto&& pad = cv->GetPad(9);
0669 pad->cd();
0670 mask_scoz(0.22,0.02,0.58, 0.98);
0671 }
0672
0673 }
0674 ++idraw;
0675 }
0676
0677 if (what == "ALL" || what == "TPOT_counts_vs_sample")
0678 {
0679
0680 auto h_array = get_histograms( "m_counts_sample" );
0681 for( const auto& h:h_array )
0682 {
0683 if( h )
0684 {
0685 h->GetXaxis()->SetRangeUser( m_sample_window.first, m_sample_window.second );
0686 h->SetMinimum(0);
0687 }
0688 }
0689
0690
0691 iret += draw_array("TPOT_counts_vs_sample", h_array, get_ref_histograms_scaled( "m_counts_sample" ) );
0692 auto cv = get_canvas("TPOT_counts_vs_sample");
0693 if( cv )
0694 {
0695 CanvasEditor cv_edit(cv);
0696 cv->Update();
0697 for( int i = 0; i < MicromegasDefs::m_nfee; ++i )
0698 {
0699
0700 auto&& pad = cv->GetPad(i+1);
0701 pad->cd();
0702 for( const auto line:{vertical_line( pad, m_sample_window_signal.first ), vertical_line( pad, m_sample_window_signal.second ) } )
0703 {
0704 line->SetLineStyle(2);
0705 line->SetLineColor(2);
0706 line->SetLineWidth(2);
0707 line->Draw();
0708 }
0709 }
0710 }
0711 ++idraw;
0712 }
0713
0714 if (what == "ALL" || what == "TPOT_hit_charge")
0715 {
0716 iret += draw_array("TPOT_hit_charge", get_histograms( "m_hit_charge" ), get_ref_histograms_scaled( "m_hit_charge" ), DrawOptions::Logy|DrawOptions::MatchRange );
0717 auto cv = get_canvas("TPOT_hit_charge");
0718 if( cv )
0719 {
0720 CanvasEditor cv_edit(cv);
0721 cv->Update();
0722 for( int i = 0; i < MicromegasDefs::m_nfee; ++i )
0723 {
0724
0725 auto&& pad = cv->GetPad(i+1);
0726 pad->cd();
0727 if( m_mean_thresholds[i] > 0 )
0728 {
0729 auto line = vertical_line( pad, m_mean_thresholds[i] );
0730 line->SetLineStyle(2);
0731 line->SetLineColor(2);
0732 line->SetLineWidth(2);
0733 line->Draw();
0734 }
0735 }
0736 }
0737 ++idraw;
0738 }
0739
0740 if (what == "ALL" || what == "TPOT_hit_multiplicity")
0741 {
0742 iret += draw_array("TPOT_hit_multiplicity", get_histograms( "m_hit_multiplicity" ), get_ref_histograms_scaled( "m_hit_multiplicity" ), DrawOptions::Logy|DrawOptions::MatchRange );
0743 ++idraw;
0744 }
0745
0746 if (what == "ALL" || what == "TPOT_waveform_vs_channel")
0747 {
0748 iret += draw_array(
0749 "TPOT_waveform_vs_channel",
0750 get_histograms( "m_wf_vs_channel" ),
0751 get_ref_histograms_scaled( "m_wf_vs_channel" ),
0752 DrawOptions::Logy|DrawOptions::MatchRange|DrawOptions::Normalize,
0753 m_triggercnt);
0754 auto cv = get_canvas("TPOT_waveform_vs_channel");
0755 if( cv )
0756 {
0757 CanvasEditor cv_edit(cv);
0758 cv->Update();
0759 for( int i = 0; i < MicromegasDefs::m_nfee; ++i )
0760 {
0761
0762
0763 auto&& pad = cv->GetPad(i+1);
0764 pad->cd();
0765 pad->Update();
0766 for( const int& channel:{64, 128, 196} )
0767 {
0768 const auto line = vertical_line( pad, channel );
0769 line->SetLineStyle(2);
0770 line->SetLineColor(1);
0771 line->SetLineWidth(1);
0772 line->Draw();
0773 }
0774 }
0775 }
0776
0777 ++idraw;
0778 }
0779
0780 if (what == "ALL" || what == "TPOT_hit_vs_channel")
0781 {
0782 iret += draw_array(
0783 "TPOT_hit_vs_channel",
0784 get_histograms( "m_hit_vs_channel" ),
0785 get_ref_histograms_scaled( "m_hit_vs_channel" ),
0786 DrawOptions::Logy|DrawOptions::MatchRange|DrawOptions::Normalize,
0787 m_triggercnt);
0788 auto cv = get_canvas("TPOT_hit_vs_channel");
0789 if( cv )
0790 {
0791 CanvasEditor cv_edit(cv);
0792 cv->Update();
0793 for( int i = 0; i < MicromegasDefs::m_nfee; ++i )
0794 {
0795
0796
0797 auto&& pad = cv->GetPad(i+1);
0798 pad->cd();
0799 pad->Update();
0800 for( const int& channel:{64, 128, 196} )
0801 {
0802 const auto line = vertical_line( pad, channel );
0803 line->SetLineStyle(2);
0804 line->SetLineColor(1);
0805 line->SetLineWidth(1);
0806 line->Draw();
0807 }
0808
0809 }
0810
0811 {
0812
0813 auto&& pad = cv->GetPad(9);
0814 pad->cd();
0815 mask_scoz(0.22,0.02,0.58, 0.98);
0816 }
0817 }
0818
0819 ++idraw;
0820 }
0821
0822
0823 if (what == "ALL" || what == "TPOT_heartbeat_vs_channel")
0824 {
0825 iret += draw_array(
0826 "TPOT_heartbeat_vs_channel",
0827 get_histograms( "m_heartbeat_vs_channel" ),
0828 get_ref_histograms_scaled( "m_heartbeat_vs_channel" ),
0829 DrawOptions::MatchRange|DrawOptions::Normalize,
0830 m_heartbeatcnt);
0831 auto cv = get_canvas("TPOT_heartbeat_vs_channel");
0832 if( cv )
0833 {
0834 CanvasEditor cv_edit(cv);
0835 cv->Update();
0836 for( int i = 0; i < MicromegasDefs::m_nfee; ++i )
0837 {
0838
0839
0840 auto&& pad = cv->GetPad(i+1);
0841 pad->cd();
0842 pad->Update();
0843 for( const int& channel:{64, 128, 196} )
0844 {
0845 const auto line = vertical_line( pad, channel );
0846 line->SetLineStyle(2);
0847 line->SetLineColor(1);
0848 line->SetLineWidth(1);
0849 line->Draw();
0850 }
0851
0852 }
0853
0854 }
0855
0856 ++idraw;
0857 }
0858
0859 if ( what == "ALL" || what == "TPOT_server_stats" )
0860 {
0861 iret += draw_server_statistics();
0862 ++idraw;
0863 }
0864
0865 if (!idraw)
0866 {
0867 std::cout << "TpotMonDraw::Draw - Unimplemented Drawing option: " << what << std::endl;
0868 iret = -1;
0869 }
0870 return iret;
0871 }
0872
0873
0874 int TpotMonDraw::SavePlot(const std::string &what, const std::string &type)
0875 {
0876 auto cl = OnlMonClient::instance();
0877 const int iret = Draw(what);
0878 if (iret) return iret;
0879
0880 for( std::size_t i =0; i < m_canvas.size(); ++i )
0881 {
0882 const auto& cv = m_canvas[i];
0883 if( cv )
0884 {
0885 std::string filename = ThisName + "_" + std::to_string(i+1) + "_" +
0886 std::to_string(cl->RunNumber()) + "." + type;
0887 cl->CanvasToPng(cv, filename);
0888 }
0889 }
0890
0891 return 0;
0892 }
0893
0894
0895 int TpotMonDraw::MakeHtml(const std::string &what)
0896 {
0897 const int iret = Draw(what);
0898 if (iret) return iret;
0899
0900 auto cl = OnlMonClient::instance();
0901
0902
0903 for( std::size_t i =0; i < m_canvas.size(); ++i )
0904 {
0905 const auto& cv = m_canvas[i];
0906 if( cv )
0907 {
0908 const auto pngfile = cl->htmlRegisterPage(*this, cv->GetName(), Form("%lu", i+1), "png");
0909 cl->CanvasToPng(cv, pngfile);
0910 }
0911 }
0912
0913
0914 {
0915 const std::string logfile = cl->htmlRegisterPage(*this, "EXPERTS/Log", "log", "html");
0916 std::ofstream out(logfile.c_str());
0917 out
0918 << "<HTML><HEAD><TITLE>Log file for run " << cl->RunNumber()
0919 << "</TITLE></HEAD>"
0920 << std::endl
0921 << "<P>Some log file output would go here."
0922 << std::endl;
0923 out.close();
0924 }
0925
0926
0927 {
0928 const std::string status = cl->htmlRegisterPage(*this, "EXPERTS/Status", "status", "html");
0929 std::ofstream out(status.c_str());
0930 out
0931 << "<HTML><HEAD><TITLE>Status file for run " << cl->RunNumber()
0932 << "</TITLE></HEAD>"
0933 << std::endl
0934 << "<P>Some status output would go here."
0935 << std::endl;
0936 out.close();
0937 cl->SaveLogFile(*this);
0938 }
0939
0940 return 0;
0941 }
0942
0943
0944 int TpotMonDraw::draw_counters()
0945 {
0946
0947 if( Verbosity() ) std::cout << "TpotMonDraw::draw_counters" << std::endl;
0948
0949
0950 auto m_counters = get_histogram( "m_counters");
0951 std::unique_ptr<TH1> m_counters_ref( normalize( get_ref_histogram( "m_counters" ), get_ref_scale_factor() ) );
0952
0953 auto cv = get_canvas("TPOT_counters");
0954 auto transparent = get_transparent_pad( cv, "TPOT_counters");
0955 if( !cv )
0956 {
0957 if( Verbosity() ) std::cout << "TpotMonDraw::draw_counters - no canvas" << std::endl;
0958 return -1;
0959 }
0960
0961 CanvasEditor cv_edit(cv);
0962
0963 if( m_counters )
0964 {
0965 m_counters->SetMinimum(0);
0966
0967 cv->cd(1);
0968 gPad->SetLeftMargin( 0.07 );
0969 gPad->SetRightMargin( 0.15 );
0970 gPad->SetBottomMargin( 0.15 );
0971 m_counters->SetFillStyle(1001);
0972 m_counters->SetFillColor(kYellow );
0973 auto copy = m_counters->DrawCopy( "hist" );
0974 copy->SetStats(false);
0975
0976 if( m_counters_ref )
0977 {
0978 m_counters_ref->SetLineColor(2);
0979 m_counters_ref->DrawCopy( "hist same" );
0980 }
0981
0982 draw_time(transparent);
0983 return 0;
0984 } else {
0985
0986 DrawDeadServer(transparent);
0987 return -1;
0988 }
0989 }
0990
0991
0992 int TpotMonDraw::draw_detector_occupancy()
0993 {
0994
0995 if( Verbosity() ) std::cout << "TpotMonDraw::draw_detector_occupancy" << std::endl;
0996
0997
0998 auto m_detector_occupancy_phi = static_cast<TH2Poly*>(get_histogram( "m_detector_occupancy_phi"));
0999 auto m_detector_occupancy_z = static_cast<TH2Poly*>(get_histogram( "m_detector_occupancy_z"));
1000
1001
1002 for( const auto& h:{m_detector_occupancy_phi,m_detector_occupancy_z} )
1003 { if(h) h->SetStats(0); }
1004
1005 auto cv = get_canvas("TPOT_detector_occupancy");
1006 auto transparent = get_transparent_pad( cv, "TPOT_detector_occupancy");
1007 if( !cv )
1008 {
1009 if( Verbosity() ) std::cout << "TpotMonDraw::draw_detector_occupancy - no canvas" << std::endl;
1010 return -1;
1011 }
1012
1013 CanvasEditor cv_edit(cv);
1014
1015 if( m_detector_occupancy_phi && m_detector_occupancy_z )
1016 {
1017 cv->cd(1);
1018 gPad->SetLeftMargin( 0.07 );
1019 gPad->SetRightMargin( 0.15 );
1020 auto copy = m_detector_occupancy_z->DrawCopy( "colz" );
1021 copy->SetStats(false);
1022 copy->GetXaxis()->SetTitleOffset(1);
1023 copy->GetYaxis()->SetTitleOffset(0.65);
1024 draw_detnames_sphenix( "Z" );
1025 draw_occupancy( m_detector_occupancy_z );
1026
1027 cv->cd(2);
1028 gPad->SetLeftMargin( 0.07 );
1029 gPad->SetRightMargin( 0.15 );
1030 copy = m_detector_occupancy_phi->DrawCopy( "colz" );
1031 copy->SetStats(false);
1032 copy->GetXaxis()->SetTitleOffset(1);
1033 copy->GetYaxis()->SetTitleOffset(0.65);
1034 draw_detnames_sphenix( "P" );
1035 draw_occupancy( m_detector_occupancy_phi );
1036
1037 draw_time(transparent);
1038 return 0;
1039
1040 } else {
1041
1042 DrawDeadServer(transparent);
1043 return -1;
1044
1045 }
1046 }
1047
1048
1049 int TpotMonDraw::draw_resist_occupancy()
1050 {
1051
1052 if( Verbosity() ) std::cout << "TpotMonDraw::draw_resist_occupancy" << std::endl;
1053
1054
1055 auto m_resist_occupancy_phi = get_histogram( "m_resist_occupancy_phi");
1056 auto m_resist_occupancy_z = get_histogram( "m_resist_occupancy_z");
1057
1058
1059 for( const auto& h:{m_resist_occupancy_phi,m_resist_occupancy_z} )
1060 { if(h) h->SetStats(0); }
1061
1062 auto cv = get_canvas("TPOT_resist_occupancy");
1063 auto transparent = get_transparent_pad( cv, "TPOT_resist_occupancy");
1064 if( !cv )
1065 {
1066 if( Verbosity() ) std::cout << "TpotMonDraw::draw_resist_occupancy - no canvas" << std::endl;
1067 return -1;
1068 }
1069
1070 CanvasEditor cv_edit(cv);
1071
1072 if( m_resist_occupancy_phi && m_resist_occupancy_z )
1073 {
1074 cv->cd(1);
1075 gPad->SetLeftMargin( 0.07 );
1076 gPad->SetRightMargin( 0.15 );
1077 auto copy = m_resist_occupancy_z->DrawCopy( "colz" );
1078 copy->SetStats(false);
1079 copy->GetXaxis()->SetTitleOffset(1);
1080 copy->GetYaxis()->SetTitleOffset(0.65);
1081 draw_detnames_sphenix( "Z" );
1082
1083 mask_scoz(0.1,0.4,0.18, 0.6);
1084
1085 cv->cd(2);
1086 gPad->SetLeftMargin( 0.07 );
1087 gPad->SetRightMargin( 0.15 );
1088 copy = m_resist_occupancy_phi->DrawCopy( "colz" );
1089 copy->SetStats(false);
1090 copy->GetXaxis()->SetTitleOffset(1);
1091 copy->GetYaxis()->SetTitleOffset(0.65);
1092 draw_detnames_sphenix( "P" );
1093
1094 draw_time(transparent);
1095 return 0;
1096
1097 } else {
1098 DrawDeadServer(transparent);
1099 return -1;
1100 }
1101 }
1102
1103
1104
1105 int TpotMonDraw::draw_server_statistics()
1106 {
1107 auto client = OnlMonClient::instance();
1108 auto cv = get_canvas("TPOT_server_stats");
1109 auto transparent = get_transparent_pad( cv, "TPOT_server_stats");
1110 CanvasEditor cv_edit(cv);
1111 transparent->cd();
1112 transparent->Clear();
1113
1114 TText PrintRun;
1115 PrintRun.SetTextFont(62);
1116 PrintRun.SetNDC();
1117 PrintRun.SetTextAlign(23);
1118 PrintRun.SetTextSize(0.04);
1119 PrintRun.SetTextColor(1);
1120 PrintRun.DrawText(0.5, 0.99, "Server Statistics");
1121 PrintRun.SetTextSize(0.02);
1122 const double vdist = 0.05;
1123 double vpos = 0.9;
1124 time_t clienttime = time(nullptr);
1125 for (const auto &server : m_ServerSet)
1126 {
1127 std::ostringstream txt;
1128 auto servermapiter = client->GetServerMap(server);
1129 if (servermapiter == client->GetServerMapEnd())
1130 {
1131 txt << "Server " << server << " is dead ";
1132 PrintRun.SetTextColor(kRed);
1133 } else {
1134 const auto gl1counts = std::get<4>(servermapiter->second);
1135 const time_t currtime = std::get<3>(servermapiter->second);
1136 txt
1137 << "Server " << server
1138 << ", run number " << std::get<1>(servermapiter->second)
1139 << ", event count: " << std::get<2>(servermapiter->second);
1140 if( gl1counts > 0 )
1141 { txt << ", gl1 count: " << gl1counts; }
1142 txt << ", current time " << ctime(&(std::get<3>(servermapiter->second)));
1143
1144 if (isHtml())
1145 {
1146
1147 clienttime = currtime;
1148 } else {
1149 txt << ", minutes since last evt: " << (clienttime - currtime)/60;
1150 }
1151
1152 if (std::get<0>(servermapiter->second) && ((clienttime - currtime)/60) < 10)
1153 {
1154 PrintRun.SetTextColor(kGray + 2);
1155 } else {
1156 PrintRun.SetTextColor(kRed);
1157 }
1158 }
1159
1160 PrintRun.DrawText(0.5, vpos, txt.str().c_str());
1161 vpos -= vdist;
1162 }
1163
1164 return 0;
1165 }
1166
1167
1168 void TpotMonDraw::draw_detnames_sphenix( const std::string& suffix)
1169 {
1170 gPad->Update();
1171 for( size_t i = 0; i < m_geometry.get_ntiles(); ++i )
1172 {
1173 const auto name = m_geometry.get_detname_sphenix(i)+suffix;
1174 const auto [x,y] = m_geometry.get_tile_center(i);
1175 auto text = new TText();
1176 text->DrawText( x-0.8*m_geometry.m_tile_length/2, y+0.5*m_geometry.m_tile_width/2, name.c_str() );
1177 text->Draw();
1178 }
1179 }
1180
1181
1182 void TpotMonDraw::draw_occupancy( TH2Poly* h)
1183 {
1184 gPad->Update();
1185 for( size_t i = 0; i < m_geometry.get_ntiles(); ++i )
1186 {
1187 const auto [x,y] = m_geometry.get_tile_center(i);
1188 const auto bin = h->FindBin(x,y);
1189 const auto value =h->GetBinContent(bin);
1190
1191 TText().DrawText( x-0.8*m_geometry.m_tile_length/2, y, Form("%.2f %%",value));
1192 }
1193 }
1194
1195
1196 TH1* TpotMonDraw::get_histogram( const std::string& name ) const
1197 {
1198 auto cl = OnlMonClient::instance();
1199 return cl->getHisto("TPOTMON_0", name );
1200 }
1201
1202
1203 TpotMonDraw::histogram_array_t TpotMonDraw::get_histograms( const std::string& name ) const
1204 {
1205 histogram_array_t out{{nullptr}};
1206 for( size_t i=0; i<m_detnames_sphenix.size(); ++i)
1207 {
1208 const auto& detector_name=m_detnames_sphenix[i];
1209 const auto hname = name + "_" + detector_name;
1210 out[i] = get_histogram( hname );
1211 if( Verbosity() )
1212 { std::cout << "TpotMonDraw::get_histograms - " << hname << (out[i]?" found":" not found" ) << std::endl; }
1213 }
1214
1215 return out;
1216 }
1217
1218
1219 TH1* TpotMonDraw::get_ref_histogram( const std::string& name ) const
1220 { return m_ref_histograms_tfile ? static_cast<TH1*>( m_ref_histograms_tfile->Get( name.c_str() ) ):nullptr; }
1221
1222
1223 TpotMonDraw::histogram_array_t TpotMonDraw::get_ref_histograms( const std::string& name ) const
1224 {
1225 histogram_array_t out{{nullptr}};
1226 for( size_t i=0; i<m_detnames_sphenix.size(); ++i)
1227 {
1228 const auto& detector_name=m_detnames_sphenix[i];
1229 const auto hname = name + "_" + detector_name;
1230 out[i] = get_ref_histogram( hname );
1231 if( Verbosity() )
1232 { std::cout << "TpotMonDraw::get_ref_histograms - " << hname << (out[i]?" found":" not found" ) << std::endl; }
1233 }
1234
1235 return out;
1236 }
1237
1238
1239 TpotMonDraw::histogram_array_t TpotMonDraw::get_ref_histograms_scaled( const std::string& name ) const
1240 {
1241 histogram_array_t source( get_ref_histograms( name ) );
1242 histogram_array_t out{{nullptr}};
1243
1244 const double scale = get_ref_scale_factor();
1245 for( size_t i=0; i<source.size(); ++i)
1246 { if( source[i] ) out[i]=normalize( source[i], scale ); }
1247
1248 return out;
1249 }
1250
1251
1252 double TpotMonDraw::get_ref_scale_factor() const
1253 {
1254 if( !m_ref_histograms_tfile ) return 0;
1255 const auto m_counters = get_histogram( "m_counters");
1256 const auto m_counters_ref = get_ref_histogram( "m_counters");
1257 if( !( m_counters && m_counters_ref ) ) return 0;
1258
1259 const double triggercnt = m_counters->GetBinContent( TpotMonDefs::kTriggerCounter );
1260 const double triggercnt_ref = m_counters_ref->GetBinContent( TpotMonDefs::kTriggerCounter );
1261 return triggercnt_ref > 0 ? triggercnt/triggercnt_ref : 0;
1262 }
1263
1264
1265 TH1* TpotMonDraw::normalize( TH1* source, double scale ) const
1266 {
1267 if( !source ) return nullptr;
1268 auto destination = static_cast<TH1*>( source->Clone() );
1269 destination->SetName( TString( source->GetName() )+"_scaled" );
1270 destination->Scale( scale );
1271 return destination;
1272 }
1273
1274
1275 int TpotMonDraw::draw_array( const std::string& name, const TpotMonDraw::histogram_array_t& histograms, const TpotMonDraw::histogram_array_t& ref_histograms, unsigned int options, double norm_factor )
1276 {
1277 if( Verbosity() ) std::cout << "TpotMonDraw::draw_array - name: " << name << std::endl;
1278
1279 auto cv = get_canvas(name);
1280 auto transparent = get_transparent_pad( cv, name);
1281 if( !cv ) return -1;
1282
1283 bool drawn = false;
1284 CanvasEditor cv_edit(cv);
1285
1286
1287 double maximum = 0;
1288 if(options&DrawOptions::MatchRange)
1289 {
1290 for( const auto& h:histograms )
1291 { if( h ) maximum = std::max( maximum, h->GetMaximum() ); }
1292 }
1293
1294
1295 if((options&DrawOptions::Normalize) && (norm_factor>0))
1296 { maximum/=norm_factor; }
1297
1298
1299 for( size_t i = 0; i < histograms.size(); ++i )
1300 {
1301 if( histograms[i] )
1302 {
1303 cv->cd(i+1);
1304 TH1* copy = nullptr;
1305 if( options&DrawOptions::Colz )
1306 {
1307 copy = histograms[i]->DrawCopy( "col" );
1308 } else {
1309
1310 histograms[i]->SetFillStyle(1001);
1311 histograms[i]->SetFillColor(kYellow );
1312 copy = histograms[i]->DrawCopy( "hist" );
1313 }
1314
1315 if( copy )
1316 {
1317 copy->SetTitle("");
1318 copy->SetStats(false);
1319 copy->GetXaxis()->SetTitleOffset(1.);
1320 copy->GetXaxis()->SetTitleSize( i==12 ? 0.075:0.08 );
1321 copy->GetXaxis()->SetLabelSize( i==12 ? 0.075:0.08 );
1322
1323 copy->GetYaxis()->SetTitleOffset( i<12 ? 1.4:1.6);
1324 copy->GetYaxis()->SetTitleSize( i<12 ? 0.08:0.07 );
1325 copy->GetYaxis()->SetLabelSize( i<12 ? 0.08:0.07 );
1326
1327
1328 if((options&DrawOptions::Normalize) && (norm_factor>0))
1329 {
1330 copy->Scale( 1./norm_factor );
1331 copy->GetYaxis()->SetTitle("counts/trigger");
1332 }
1333
1334
1335 if(options&DrawOptions::MatchRange)
1336 {
1337 copy->SetMaximum( 1.2*maximum );
1338 copy->SetMinimum(0);
1339 }
1340
1341 }
1342
1343
1344 if( ref_histograms[i] )
1345 {
1346 ref_histograms[i]->SetLineColor(2);
1347
1348 const auto& ref_copy = ref_histograms[i]->DrawCopy("hist same" );
1349 ref_copy->SetStats(false);
1350
1351
1352 if((options&DrawOptions::Normalize) && (norm_factor>0))
1353 { ref_copy->Scale( 1./norm_factor ); }
1354
1355 }
1356
1357
1358 if( options&DrawOptions::Logx )
1359 { gPad->SetLogx( true ); }
1360
1361 if( options&DrawOptions::Logy && histograms[i]->GetEntries() > 0 )
1362 {
1363 gPad->SetLogy( true );
1364 if((options&DrawOptions::Normalize) && (norm_factor>0))
1365 {
1366 copy->SetMinimum(1./norm_factor);
1367 } else {
1368 copy->SetMinimum(1);
1369 }
1370 }
1371
1372 if( options&DrawOptions::Logz )
1373 { gPad->SetLogz( true ); }
1374
1375
1376 const auto label = Form( "%s (%02i)", m_detnames_sphenix[i].c_str(), m_mapping.get_fee_id_list()[i]);
1377 draw_text( (i%4) ? 0.5:0.6, 0.9, label, (i%4) ? 0.1:0.094 );
1378
1379 drawn = true;
1380 }
1381 }
1382
1383 if( drawn )
1384 {
1385 draw_time(transparent);
1386 return 0;
1387 } else {
1388 DrawDeadServer(transparent);
1389 return -1;
1390 }
1391
1392
1393 for( auto h:ref_histograms ) { delete h; }
1394 return 0;
1395 }