NAGASH 0.9.8
Next Generation Analysis System
Loading...
Searching...
No Matches
FigureTool.cxx
Go to the documentation of this file.
1#include "NAGASH/FigureTool.h"
2#include "NAGASH/HistTool.h"
3
4using namespace NAGASH;
5
241// Functions for FigureStyleHelper
242
243FigureStyleHelper::FigureStyleHelper(std::shared_ptr<MSGTool> MSG)
244{
245 msg = MSG;
246
247 gStyle->SetLineStyleString(2, "[12 12]"); // postscript dashes
248 gStyle->SetFrameBorderMode(0);
249 gStyle->SetFrameFillColor(0);
250 gStyle->SetCanvasBorderMode(0);
251 gStyle->SetCanvasColor(0);
252 gStyle->SetPadBorderMode(0);
253 gStyle->SetPadColor(0);
254 gStyle->SetStatColor(0);
255 gStyle->SetPaperSize(20, 26);
256
257 /*
258 const double CL = 0.0;
259 const double CH = 1.0;
260
261 double nstops[7] = {0, 0.17, 0.33, 0.50, 0.67, 0.83, 1.0};
262 double Red[7] = {CH, CH, CL, CL, CL, CH, CH};
263 double Green[7] = {CL, CH, CH, CH, CL, CL, CL};
264 double Blue[7] = {CL, CL, CL, CH, CH, CH, CL};
265
266 colorstart = TColor::CreateGradientColorTable(7, nstops, Red, Green, Blue, 200);
267 */
268
269 /*
270 for (int index = 0; index < 200; index++)
271 MSGUser()->MSG_INFO(index, " ", gROOT->GetColor(colorstart + index)->GetRed(), " ", gROOT->GetColor(colorstart + index)->GetGreen(), " ", gROOT->GetColor(colorstart + index)->GetBlue());
272 */
273
274 // set the palette for 2D plots
275 // gStyle->SetPalette(0);
276}
277
279{
280 FigureElement *root = pad->GetRootElement();
281 FigureSquareRange canvasrange = root->Range_Total;
282 FigureSquareRange padrange = pad->Range_Total;
283
284 // set ticks above and right
285 pad->GetPad()->SetTicks();
286
287 // get the axis from the first element
288 TAxis *Xaxis = nullptr;
289 TAxis *Yaxis = nullptr;
290 TAxis *Zaxis = nullptr;
291
292 bool is_for_hstack = false;
293
294 std::shared_ptr<FigureElement> firstelement = pad->GetLinkElement(0);
295
296 if (firstelement->IsType("FigureHist1D"))
297 {
298 Xaxis = (std::dynamic_pointer_cast<FigureHist1D>(firstelement))->GetHist()->GetXaxis();
299 Yaxis = (std::dynamic_pointer_cast<FigureHist1D>(firstelement))->GetHist()->GetYaxis();
300 }
301 else if (firstelement->IsType("FigureHStack"))
302 {
303 Xaxis = (std::dynamic_pointer_cast<FigureHStack>(firstelement))->empty_hist->GetXaxis();
304 Yaxis = (std::dynamic_pointer_cast<FigureHStack>(firstelement))->empty_hist->GetYaxis();
305 is_for_hstack = true;
306 }
307 else if (firstelement->IsType("FigureGraph1D"))
308 {
309 Xaxis = (std::dynamic_pointer_cast<FigureGraph1D>(firstelement))->GetGraph()->GetXaxis();
310 Yaxis = (std::dynamic_pointer_cast<FigureGraph1D>(firstelement))->GetGraph()->GetYaxis();
311 }
312 else if (firstelement->IsType("FigureFunc1D"))
313 {
314 Xaxis = (std::dynamic_pointer_cast<FigureFunc1D>(firstelement))->GetFunc()->GetXaxis();
315 Yaxis = (std::dynamic_pointer_cast<FigureFunc1D>(firstelement))->GetFunc()->GetYaxis();
316 }
317 else if (firstelement->IsType("FigureHist2D"))
318 {
319 Xaxis = (std::dynamic_pointer_cast<FigureHist2D>(firstelement))->GetHist()->GetXaxis();
320 Yaxis = (std::dynamic_pointer_cast<FigureHist2D>(firstelement))->GetHist()->GetYaxis();
321 Zaxis = (std::dynamic_pointer_cast<FigureHist2D>(firstelement))->GetHist()->GetZaxis();
322 }
323
324 // Set Margin
325 int n_bottom = canvasrange.RT_Y * TITLE_MARGIN_PERCENT;
326 if (pad->NeedBottomMargin())
327 pad->GetPad()->SetBottomMargin(((double)n_bottom) / (padrange.RT_Y - padrange.LB_Y));
328 else
329 {
330 pad->GetPad()->SetBottomMargin(0);
331 n_bottom = 0;
332 }
333
334 int n_left = canvasrange.RT_X * TITLE_MARGIN_PERCENT;
335 if (pad->NeedLeftMargin())
336 pad->GetPad()->SetLeftMargin(((double)n_left) / (padrange.RT_X - padrange.LB_X));
337 else
338 {
339 pad->GetPad()->SetLeftMargin(0);
340 n_left = 0;
341 }
342
343 int n_top = canvasrange.RT_Y * TOP_BLANK_MARGIN_PERCENT;
344 if (padrange.RT_Y > canvasrange.RT_Y - n_top)
345 {
346 pad->GetPad()->SetTopMargin(((double)padrange.RT_Y - canvasrange.RT_Y + n_top) / (padrange.RT_Y - padrange.LB_Y));
347 n_top = padrange.RT_Y - canvasrange.RT_Y + n_top;
348 }
349 else
350 {
351 pad->GetPad()->SetTopMargin(0);
352 n_top = 0;
353 }
354
355 int n_right = canvasrange.RT_X * (TITLE_MARGIN_PERCENT + COLZ_MARGIN_PERCENT);
356 int n_right_blank = canvasrange.RT_X * RIGHT_BLANK_MARGIN_PERCENT;
357 if (padrange.RT_X > canvasrange.RT_X - n_right_blank)
358 n_right_blank = padrange.RT_X - canvasrange.RT_X + n_right_blank;
359 else
360 n_right_blank = 0;
361 if (pad->NeedRightMargin() == false)
362 n_right = 0;
363 if (n_right < n_right_blank)
364 n_right = n_right_blank;
365 pad->GetPad()->SetRightMargin(((double)n_right) / (padrange.RT_X - padrange.LB_X));
366
367 // Set Ticks, Title, Label and Division
368 int n_axis = TICK_LENGTH_PERCENT * canvasrange.RT_X;
369 int n_label = TEXT_SIZE_PERCENT * canvasrange.RT_X;
370 int div_n1_x = (double)DIVISION_N1 * (padrange.RT_X - padrange.LB_X - n_left - n_right) / canvasrange.RT_X;
371 int div_n1_y = (double)DIVISION_N1 * (padrange.RT_Y - padrange.LB_Y - n_top - n_bottom) / canvasrange.RT_X;
372 int div_n1_z = (double)DIVISION_N1 * (padrange.RT_Y - padrange.LB_Y - n_top - n_bottom) / canvasrange.RT_X;
373
374 if (2 < div_n1_x < 5)
375 div_n1_x = 5;
376 if (2 < div_n1_y < 5)
377 div_n1_y = 5;
378 if (2 < div_n1_z < 5)
379 div_n1_z = 5;
380
381 int div_n_x = div_n1_x + 100 * DIVISION_N2 + 10000 * DIVISION_N3;
382 int div_n_y = div_n1_y + 100 * DIVISION_N2 + 10000 * DIVISION_N3;
383 int div_n_z = div_n1_z + 100 * DIVISION_N2 + 10000 * DIVISION_N3;
384
385 if (Xaxis)
386 {
387 /*
388 if (((double)n_axis) / (padrange.RT_Y - padrange.LB_Y) > 0.05)
389 MSGUser()->MSG_WARNING("TICK_LENGTH_PERCENT = ", TICK_LENGTH_PERCENT, " is too large for Pad ", pad->GetName().TString::Data(), " X axis!");
390 */
391 Xaxis->SetTickLength(((double)n_axis) / (padrange.RT_Y - padrange.LB_Y));
392 Xaxis->SetNdivisions(div_n_x);
393 Xaxis->SetLabelFont(TEXT_FONT * 10 + 3);
394 Xaxis->SetLabelSize(n_label);
395 Xaxis->SetTitleFont(TEXT_FONT * 10 + 3);
396 Xaxis->SetTitleSize(n_label);
397 Xaxis->SetMaxDigits(4);
398
399 if (!pad->user_set_title_offset)
400 {
401 double offset = -0.1 + 6.13 * ((double)n_bottom) / (padrange.RT_Y - padrange.LB_Y);
402 if (offset < 1)
403 offset = 1;
404 Xaxis->SetTitleOffset(offset);
405 }
406 else
407 {
408 Xaxis->SetTitleOffset(pad->GetXTitleOffset());
409 }
410 if (pad->NeedBottomMargin())
411 Xaxis->SetTitle(pad->GetXTitle().TString::Data());
412 }
413 if (Yaxis)
414 {
415 /*
416 if (((double)n_axis) / (padrange.RT_X - padrange.LB_X) > 0.05)
417 MSGUser()->MSG_WARNING("TICK_LENGTH_PERCENT = ", TICK_LENGTH_PERCENT, " is too large for Pad ", pad->GetName().TString::Data(), " Y axis!");
418 */
419 Yaxis->SetTickLength(((double)n_axis) / (padrange.RT_X - padrange.LB_X));
420 Yaxis->SetNdivisions(div_n_y);
421 // Yaxis->SetNdivisions(505);
422 Yaxis->SetLabelFont(TEXT_FONT * 10 + 3);
423 Yaxis->SetLabelSize(n_label);
424 Yaxis->SetTitleFont(TEXT_FONT * 10 + 3);
425 Yaxis->SetTitleSize(n_label);
426 Yaxis->SetMaxDigits(3);
427
428 if (!pad->user_set_title_offset)
429 {
430 double offset = -0.25 + 12.666 * ((double)n_left) / (padrange.RT_X - padrange.LB_X);
431 if (offset < 1)
432 offset = 1;
433 Yaxis->SetTitleOffset(offset);
434 }
435 else
436 {
437 Yaxis->SetTitleOffset(pad->GetYTitleOffset());
438 }
439
440 if (pad->NeedLeftMargin())
441 Yaxis->SetTitle(pad->GetYTitle().TString::Data());
442 }
443 if (Zaxis)
444 {
445 /*
446 if (((double)n_axis) / (padrange.RT_X - padrange.LB_X) > 0.05)
447 MSGUser()->MSG_WARNING("TICK_LENGTH_PERCENT = ", TICK_LENGTH_PERCENT, " is too large for Pad ", pad->GetName().TString::Data(), " Y axis!");
448 */
449 Zaxis->SetTickLength(((double)n_axis) / (padrange.RT_X - padrange.LB_X));
450 Zaxis->SetNdivisions(div_n_z);
451 Zaxis->SetLabelFont(TEXT_FONT * 10 + 3);
452 Zaxis->SetLabelSize(n_label);
453 Zaxis->SetTitleFont(TEXT_FONT * 10 + 3);
454 Zaxis->SetTitleSize(n_label);
455 Zaxis->SetMaxDigits(4);
456
457 if (!pad->user_set_title_offset)
458 {
459 double offset = -0.25 + 12.666 * ((double)n_left) / (padrange.RT_X - padrange.LB_X);
460 if (offset < 1)
461 offset = 1;
462 Zaxis->SetTitleOffset(offset);
463 }
464 else
465 {
466 Zaxis->SetTitleOffset(pad->GetZTitleOffset());
467 }
468
469 if (pad->NeedRightMargin())
470 Zaxis->SetTitle(pad->GetZTitle().TString::Data());
471 }
472
473 // set the axis range, if user not set y axis range and legend position, auto adjust the range of y axis
474 if (pad->user_set_rangex && Xaxis)
475 Xaxis->SetRangeUser(pad->min_xaxis, pad->max_xaxis);
476 if (pad->user_set_rangey && Yaxis)
477 Yaxis->SetRangeUser(pad->min_yaxis, pad->max_yaxis);
478 if (pad->user_set_rangez && Zaxis)
479 Zaxis->SetRangeUser(pad->min_zaxis, pad->max_zaxis);
480
481 if (Xaxis)
482 {
483 pad->max_xaxis = Xaxis->GetXmax();
484 pad->min_xaxis = Xaxis->GetXmin();
485 }
486
487 if (Yaxis)
488 {
489 pad->max_yaxis = Yaxis->GetXmax();
490 pad->min_yaxis = Yaxis->GetXmin();
491 }
492
493 if (Zaxis)
494 {
495 pad->max_zaxis = Zaxis->GetXmax();
496 pad->min_zaxis = Zaxis->GetXmin();
497 }
498
499 // auto adjust y range to plot the legend
500 if (!pad->user_set_rangey && pad->plot_legend && Yaxis)
501 {
502 double max_yaxis_adjust = 0;
503 double min_yaxis_adjust = 0;
504 for (int i = 0; i < pad->GetNLinkElement(); i++)
505 {
506 auto elem = pad->GetLinkElement(i);
507 double ymin, ymax;
508 if (elem->IsType("FigureHist1D"))
509 std::tie(ymin, ymax) = (std::dynamic_pointer_cast<FigureHist1D>(elem))->GetMinAndMax(pad->min_xaxis, pad->max_xaxis);
510 if (elem->IsType("FigureHStack"))
511 std::tie(ymin, ymax) = (std::dynamic_pointer_cast<FigureHStack>(elem))->GetMinAndMax(pad->min_xaxis, pad->max_xaxis);
512 if (elem->IsType("FigureGraph1D"))
513 std::tie(ymin, ymax) = (std::dynamic_pointer_cast<FigureGraph1D>(elem))->GetMinAndMax(pad->min_xaxis, pad->max_xaxis);
514 if (elem->IsType("FigureFunc1D"))
515 std::tie(ymin, ymax) = (std::dynamic_pointer_cast<FigureFunc1D>(elem))->GetMinAndMax(pad->min_xaxis, pad->max_xaxis);
516
517 if (i == 0)
518 {
519 min_yaxis_adjust = ymin;
520 max_yaxis_adjust = ymax;
521 }
522 else
523 {
524 if (ymin < min_yaxis_adjust)
525 min_yaxis_adjust = ymin;
526 if (ymax > max_yaxis_adjust)
527 max_yaxis_adjust = ymax;
528 }
529 }
530
531 if (is_for_hstack)
532 min_yaxis_adjust = 0;
533
534 if (!pad->user_set_legend_position)
535 {
536 double length_pad;
537 int nrows = pad->n_colored_objects / pad->legend_column;
538 if (pad->n_colored_objects % pad->legend_column != 0)
539 nrows += 1;
540
541 if ((1 + nrows) * LeftPercentage + 0.04 < 0.5)
542 length_pad = (max_yaxis_adjust - min_yaxis_adjust) / ((1 - (1 + nrows) * LeftPercentage - 0.04));
543 else
544 length_pad = (max_yaxis_adjust - min_yaxis_adjust) / 0.5;
545
546 max_yaxis_adjust += (0.04 + (1 + nrows) * LeftPercentage) * length_pad * 1.2;
547 min_yaxis_adjust += -LeftPercentage * length_pad;
548
549 if (is_for_hstack)
550 min_yaxis_adjust = 0;
551 }
552 else
553 {
554 double top_percentage = 1 - pad->GetPad()->GetTopMargin() - pad->legend_ymin;
555 double length_pad = (max_yaxis_adjust - min_yaxis_adjust) / (1 - top_percentage);
556
557 max_yaxis_adjust += top_percentage * length_pad * 1.2;
558 min_yaxis_adjust += -LeftPercentage * length_pad;
559
560 if (is_for_hstack)
561 min_yaxis_adjust = 0;
562 }
563
564 Yaxis->SetRangeUser(min_yaxis_adjust, max_yaxis_adjust);
565 }
566
567 // set the legend position and style
568 if (pad->plot_legend)
569 {
570 pad->legend->SetFillColor(0);
571 pad->legend->SetFillStyle(0);
572 pad->legend->SetLineColor(0);
573 pad->legend->SetLineWidth(0);
574 pad->legend->SetTextSize(LEGEND_TEXT_SIZE_PERCENT);
575 pad->legend->SetTextFont(TEXT_FONT * 10 + 2);
576
578 {
579 pad->legend->SetX1(pad->legend_xmin);
580 pad->legend->SetX2(pad->legend_xmax);
581 pad->legend->SetY1(pad->legend_ymin);
582 pad->legend->SetY2(pad->legend_ymax);
583 }
584 else
585 {
586 if (pad->user_set_rangey)
587 {
588 auto titleguard = MSGUser()->StartTitleWithGuard("FigureStyleHelper::SetPadStyle");
589 MSGUser()->MSG_WARNING("pad y axis range set but legend position not set, user should manually set the position of legend");
590 }
591
592 double percentage;
593
594 if (pad->n_colored_objects % pad->legend_column == 0)
595 percentage = (1 + (int)(pad->n_colored_objects / pad->legend_column)) * LeftPercentage;
596 else
597 percentage = (2 + (int)(pad->n_colored_objects / pad->legend_column)) * LeftPercentage;
598
599 pad->legend->SetX1(1 - pad->GetPad()->GetRightMargin() - 0.04 - 0.23 * pad->legend_column);
600 pad->legend->SetX2(1 - pad->GetPad()->GetRightMargin() - 0.04);
601 pad->legend->SetY1(1 - pad->GetPad()->GetTopMargin() - percentage);
602 pad->legend->SetY2(1 - pad->GetPad()->GetTopMargin() - 0.04);
603
604 // MSGUser()->MSG_INFO(pad->GetPad()->GetLeftMargin() + 0.04, " ", 1 - pad->GetPad()->GetLeftMargin() - 0.04, " ", 1 - pad->GetPad()->GetTopMargin() - percentage, " ", 1 - pad->GetPad()->GetTopMargin() - 0.04);
605 }
606 }
607
608 if (pad->AxisOptionFunc)
609 {
610 pad->AxisOptionFunc(Xaxis, Yaxis, Zaxis);
611 }
612}
613
615{
616 hist->GetHist()->SetTitle("");
617 hist->GetHist()->SetStats(0);
618
619 // calculate the color
620 /*
621 int index = hist->index_in_pad;
622 int nelements = ((FigurePad *)(hist->GetMotherElement()))->GetNColoredObjects();
623 int step = 199 / nelements;
624 if (step > 66)
625 step = 66;
626
627 if (index % 2 == 0)
628 index = index / 2;
629 else
630 index = nelements - ((index + 1) / 2);
631
632 int ncolor = index * step + colorstart;
633 */
634
635 // color scheme in NGFigure
636 int index = hist->index_in_pad % 12;
637 int round = (hist->index_in_pad - index) / 12 * 2 + 1;
638 Color_t mypalette[12] = {kRed, kBlue, kGreen, kPink, kAzure, kOrange, kMagenta, kCyan, kYellow, kViolet, kTeal, kSpring + 1};
639 Color_t ncolor = mypalette[index] + round;
640
641 hist->GetHist()->SetLineColor(ncolor);
642 hist->GetHist()->SetMarkerColor(ncolor);
643 hist->GetHist()->SetLineWidth(2);
644 hist->GetHist()->SetMarkerSize(0);
645 hist->GetHist()->SetFillStyle(0);
646 if (hist->ForHStack)
647 {
648 hist->GetHist()->SetFillStyle(1001);
649 hist->GetHist()->SetFillColor(ncolor);
650 hist->GetHist()->SetLineWidth(0);
651 }
652
653 // MSGUser()->MSG_INFO(index, " ", ncolor, " ", gROOT->GetColor(ncolor)->GetRed(), " ", gROOT->GetColor(ncolor)->GetGreen(), " ", gROOT->GetColor(ncolor)->GetBlue());
654}
655
657{
658 graph->GetGraph()->SetTitle("");
659
660 // color scheme in NGFigure
661 int index = graph->index_in_pad % 12;
662 int round = (graph->index_in_pad - index) / 12 * 2 + 1;
663 Color_t mypalette[12] = {kRed, kBlue, kGreen, kPink, kAzure, kOrange, kMagenta, kCyan, kYellow, kViolet, kTeal, kSpring + 1};
664 Color_t ncolor = mypalette[index] + round;
665
666 int Marker_Style[6] = {20, 21, 22, 23, 29, 33};
667
668 graph->GetGraph()->SetLineWidth(2);
669 graph->GetGraph()->SetLineColor(ncolor);
670 graph->GetGraph()->SetLineStyle(1);
671
672 FigureElement *root = graph->GetRootElement();
673 FigureSquareRange canvasrange = root->Range_Total;
674
675 graph->GetGraph()->SetMarkerSize(0.002 * (canvasrange.RT_Y - canvasrange.LB_Y));
676 graph->GetGraph()->SetMarkerColor(ncolor);
677 graph->GetGraph()->SetMarkerStyle(Marker_Style[graph->index_in_pad % 6]);
678 graph->GetGraph()->SetFillStyle(0);
679}
680
682{
683 hist->mygraph->SetTitle("");
684
685 // color scheme in NGFigure
686 int index = hist->index_in_pad % 12;
687 int round = (hist->index_in_pad - index) / 12 * 2 + 1;
688 Color_t mypalette[12] = {kRed, kBlue, kGreen, kPink, kAzure, kOrange, kMagenta, kCyan, kYellow, kViolet, kTeal, kSpring + 1};
689 Color_t ncolor = mypalette[index] + round;
690
691 int Marker_Style[6] = {20, 21, 22, 23, 29, 33};
692
693 hist->mygraph->SetLineWidth(2);
694 hist->mygraph->SetLineColor(ncolor);
695 hist->mygraph->SetLineStyle(1);
696
697 FigureElement *root = hist->GetRootElement();
698 FigureSquareRange canvasrange = root->Range_Total;
699
700 hist->mygraph->SetMarkerSize(0.002 * (canvasrange.RT_Y - canvasrange.LB_Y));
701 hist->mygraph->SetMarkerColor(ncolor);
702 hist->mygraph->SetMarkerStyle(Marker_Style[hist->index_in_pad % 6]);
703 hist->mygraph->SetFillStyle(0);
704}
705
707{
708 func->GetFunc()->SetTitle("");
709 // color scheme in NGFigure
710 int index = func->index_in_pad % 12;
711 int round = (func->index_in_pad - index) / 12 * 2 + 1;
712 Color_t mypalette[12] = {kRed, kBlue, kGreen, kPink, kAzure, kOrange, kMagenta, kCyan, kYellow, kViolet, kTeal, kSpring + 1};
713 Color_t ncolor = mypalette[index] + round;
714
715 func->GetFunc()->SetLineWidth(2);
716 func->GetFunc()->SetLineColor(ncolor);
717 func->GetFunc()->SetFillColor(ncolor);
718 func->GetFunc()->SetMarkerColor(ncolor);
719 func->GetFunc()->SetFillStyle(0);
720}
721
723{
724 hist->GetHist()->SetTitle("");
725 hist->GetHist()->SetStats(0);
726 // color scheme in NGFigure
727 int index = hist->index_in_pad % 12;
728 int round = (hist->index_in_pad - index) / 12 * 2 + 1;
729 Color_t mypalette[12] = {kRed, kBlue, kGreen, kPink, kAzure, kOrange, kMagenta, kCyan, kYellow, kViolet, kTeal, kSpring + 1};
730 Color_t ncolor = mypalette[index] + round;
731
732 hist->GetHist()->SetLineColor(ncolor);
733 hist->GetHist()->SetFillColor(ncolor);
734}
735
737{
738 latex->mylatex->SetTextFont(TEXT_FONT * 10 + 2);
739 latex->mylatex->SetTextSize(LEGEND_TEXT_SIZE_PERCENT);
740}
741
745
746// Functions for FigureElement
747
748FigureElement::FigureElement(std::shared_ptr<MSGTool> MSG, std::shared_ptr<FigureStyleHelper> shelper, const TString &elementname, const TString &tyname, FigureElement *mother)
749{
750 msg = MSG;
751 stylehelper = shelper;
752 name = elementname;
753 castname = tyname;
754 MotherElement = mother;
755}
756
758{
759 MSGUser()->MSG_ERROR("Function FigureElement::DrawElement Should be override!!!");
760}
761
763{
764 // This is usually empty override if necessary
765}
766
768{
769 // This is usually empty override if necessary
770}
771
773{
774 DrawElement();
775 for (auto &iter : LinkedElement)
776 {
777 CD();
778 iter->Draw();
779 }
780 SetStyle();
781}
782
783bool FigureElement::Contain(std::shared_ptr<FigureElement> subelement)
784{
785 bool contain = false;
786 for (int i = 0; i < Range_vec.size(); i++)
787 {
788 for (int j = 0; j < subelement->Range_vec.size(); j++)
789 {
790 if (Contain(Range_vec[i], (subelement->Range_vec)[j]) == true)
791 contain = true;
792 }
793 }
794
795 return contain;
796}
797
799{
800 FigureElement *root = this;
801
802 while (root->MotherElement != nullptr)
803 root = root->MotherElement;
804
805 return root;
806}
807
808std::shared_ptr<FigureElement> FigureElement::FindLinkElement(const TString &name)
809{
810 if (auto findresult = MapLinkedElement.find(name); findresult != MapLinkedElement.end())
811 return LinkedElement.at(findresult->second);
812
813 for (auto &iter : LinkedElement)
814 {
815 auto foundelement = iter->FindLinkElement(name);
816 if (foundelement != nullptr)
817 return foundelement;
818 }
819
820 return nullptr;
821}
822
823std::shared_ptr<FigureElement> FigureElement::TraceElement(const TString &name)
824{
826 return root->FindLinkElement(name);
827}
828
829bool FigureElement::CheckDuplicate(const TString &elementname)
830{
831 if (MapLinkedElement.find(elementname) != MapLinkedElement.end())
832 {
833 auto titleguard = MSGUser()->StartTitleWithGuard("FigureElement::CheckDuplicate");
834 MSGUser()->MSG_ERROR("can not book element with same name ", elementname);
835 return false;
836 }
837
838 return true;
839}
840
842{
843 bool contain = true;
844 if (A.LB_X > SubA.LB_X)
845 contain = false;
846 if (A.LB_Y > SubA.LB_Y)
847 contain = false;
848 if (A.RT_X < SubA.RT_X)
849 contain = false;
850 if (A.RT_Y < SubA.RT_Y)
851 contain = false;
852
853 return contain;
854}
855
856int FigureElement::GetLinkIndex(const TString &name)
857{
858 auto titleguard = MSGUser()->StartTitleWithGuard("FigureElement::GetLinkIndex");
859 if (auto findresult = MapLinkedElement.find(name); findresult != MapLinkedElement.end())
860 return findresult->second;
861 else
862 {
863 MSGUser()->MSG_ERROR("does not find element ", name, " return -1");
864 return -1;
865 }
866}
867
868std::shared_ptr<FigureElement> FigureElement::GetLinkElement(int index)
869{
870 auto titleguard = MSGUser()->StartTitleWithGuard("FigureElement::GetLinkElement");
871 if (index < 0 || index >= LinkedElement.size())
872 {
873 MSGUser()->MSG_ERROR("index out of range, return nullptr");
874 return nullptr;
875 }
876 else
877 return LinkedElement[index];
878}
879
880// Functions for FigureHist1D
881
882FigureHist1D::FigureHist1D(std::shared_ptr<MSGTool> MSG, std::shared_ptr<FigureStyleHelper> shelper, const TString &elementname, const TString &linkinfo, const TString &option, FigureElement *mother, std::function<void(TH1D *)> optionfunc)
883 : FigureElement(MSG, shelper, elementname, "FigureHist1D", mother)
884{
885 LinkInfo = linkinfo;
886 DrawOption = option;
887 OptionFunc = optionfunc;
888 FromHistLink = true;
889}
890
891FigureHist1D::FigureHist1D(std::shared_ptr<MSGTool> MSG, std::shared_ptr<FigureStyleHelper> shelper, const TString &elementname, TH1D *hist, const TString &option, FigureElement *mother, std::function<void(TH1D *)> optionfunc)
892 : FigureElement(MSG, shelper, elementname, "FigureHist1D", mother)
893{
894 myhist = (TH1D *)hist->Clone(TString::Format("Temp_%s", elementname.TString::Data()).TString::Data());
895 myhist->SetDirectory(0);
896 DrawOption = option;
897 OptionFunc = optionfunc;
898 FromHistLink = false;
899}
900
901// Draw histogram as TGraph rather than TH1D
902FigureHist1D::FigureHist1D(std::shared_ptr<MSGTool> MSG, std::shared_ptr<FigureStyleHelper> shelper, const TString &elementname, TH1D *hist, const TString &option, FigureElement *mother, std::function<void(TGraph *)> optionfunc)
903 : FigureElement(MSG, shelper, elementname, "FigureHist1D", mother)
904{
905 myhist = (TH1D *)hist->Clone(TString::Format("Temp_%s", elementname.TString::Data()).TString::Data());
906 myhist->SetDirectory(0);
907 DrawOption = option;
908 TGraphOptionFunc = optionfunc;
909 FromHistLink = false;
910 DrawAsTGraph = true;
911}
912
913FigureHist1D::FigureHist1D(std::shared_ptr<MSGTool> MSG, std::shared_ptr<FigureStyleHelper> shelper, const TString &elementname, const TString &linkinfo, const TString &option, FigureElement *mother, std::function<void(TGraph *)> optionfunc)
914 : FigureElement(MSG, shelper, elementname, "FigureHist1D", mother)
915{
916 LinkInfo = linkinfo;
917 DrawOption = option;
918 TGraphOptionFunc = optionfunc;
919 FromHistLink = true;
920 DrawAsTGraph = true;
921}
922
924{
925 if (FromHistLink == true && myhist == nullptr)
927 if (myhist == nullptr)
928 return;
929 if (ForHStack)
930 return;
931
932 if (!DrawAsTGraph)
933 myhist->Draw(DrawOption);
934 else
935 {
936 // convert the histogram to TGraph
937 mygraph = new TGraphErrors((TH1 *)myhist);
938 mygraph->GetXaxis()->SetRangeUser(myhist->GetXaxis()->GetXmin(), myhist->GetXaxis()->GetXmax());
939
940 // set ex to zero
941 for (int i = 0; i < mygraph->GetN(); i++)
942 mygraph->SetPointError(i, 0, mygraph->GetErrorY(i));
943
944 mygraph->Draw(DrawOption);
945 }
946}
947
949{
950 if (!DrawAsTGraph)
951 {
952 StyleUser()->SetHist1DStyle(this);
954 }
955 else
956 {
957 StyleUser()->SetHist1DGraphStyle(this);
958 TGraphOptionFunc((TGraph *)mygraph);
959 }
960}
961
963{
964 delete myhist;
965 if (mygraph)
966 delete mygraph;
967}
968
970{
971 if (LinkInfo.TString::BeginsWith("RATIO"))
972 return "RATIO";
973 if (LinkInfo.TString::BeginsWith("PULL"))
974 return "PULL";
975 if (LinkInfo.TString::BeginsWith("DELTA"))
976 return "DELTA";
977 if (LinkInfo.TString::BeginsWith("CHI2"))
978 return "CHI2";
979 return "UNKNOWN";
980}
981
982std::vector<TString> FigureHist1D::GetLinkObject()
983{
984 std::vector<TString> LinkObjectName;
985 TString name = "";
986 bool start = false;
987 for (int i = 0; i < LinkInfo.Length(); i++)
988 {
989 if (LinkInfo(i) == '/' && start == true)
990 {
991 LinkObjectName.push_back(name);
992 name = "";
993 }
994
995 if (start == true && LinkInfo(i) != '/')
996 name = name + LinkInfo(i);
997
998 if (LinkInfo(i) == '/' && start == false)
999 {
1000 start = true;
1001 name = "";
1002 } // Start
1003 }
1004
1005 return LinkObjectName;
1006}
1007
1009{
1010 TString LinkMode = GetLinkMode();
1011 if (LinkMode.TString::EqualTo("UNKNOWN"))
1012 {
1013 MSGUser()->MSG_ERROR("FigureHist1D ", GetName().TString::Data(), " cannot be generated from ", LinkMode.TString::Data());
1014 return;
1015 }
1016
1017 auto LinkObjectName = GetLinkObject();
1018 std::vector<std::shared_ptr<FigureElement>> LinkObject;
1019 for (int i = 0; i < LinkObjectName.size(); i++)
1020 {
1021 auto obj = TraceElement(LinkObjectName[i]);
1022 if (obj != nullptr)
1023 LinkObject.push_back(obj);
1024 else
1025 MSGUser()->MSG_ERROR("can not find linked element ", LinkObjectName[i]);
1026 }
1027
1028 std::vector<TH1D *> LinkHists;
1029
1030 auto CheckLinkObjectType = [&](int num) -> bool
1031 {
1032 for (int i = 0; i < num; i++)
1033 {
1034 if (LinkObject[i]->IsType("FigureHist1D"))
1035 {
1036 if ((std::dynamic_pointer_cast<FigureHist1D>(LinkObject[i]))->GetHist() == nullptr)
1037 (std::dynamic_pointer_cast<FigureHist1D>(LinkObject[i]))->CreateHistFromHistLink();
1038
1039 LinkHists.emplace_back(std::dynamic_pointer_cast<FigureHist1D>(LinkObject[i])->GetHist());
1040 }
1041 else if (LinkObject[i]->IsType("FigureHStack"))
1042 {
1043 LinkHists.emplace_back(std::dynamic_pointer_cast<FigureHStack>(LinkObject[i])->GetTotalHist());
1044 }
1045 else
1046 {
1047 MSGUser()->MSG_ERROR("Link Object must be FigureHist1D or FigureHStack");
1048 return false;
1049 }
1050 }
1051
1052 return true;
1053 };
1054
1055 if (LinkMode.TString::EqualTo("RATIO"))
1056 {
1057 // This needs two object
1058 if (LinkObject.size() != 2)
1059 {
1060 MSGUser()->MSG_ERROR("RATIO Link Needs two objects!!! FigureHist1D:", GetName().TString::Data(), " has ", LinkObject.size());
1061 return;
1062 }
1063
1064 if (!CheckLinkObjectType(2))
1065 return;
1066
1067 std::shared_ptr<HistTool> histtool = std::make_shared<HistTool>(MSGUser());
1068 TH1D *hist0 = nullptr;
1069 TH1D *hist1 = nullptr;
1070 hist0 = (TH1D *)(LinkHists[0]->Clone("TempRatio0_" + GetName()));
1071 if (LinkObject[0] == LinkObject[1])
1072 hist1 = hist0;
1073 else
1074 hist1 = (TH1D *)(LinkHists[1]->Clone("TempRatio1_" + GetName()));
1075
1076 myhist = (TH1D *)hist0->Clone(GetName().TString::Data());
1077 histtool->Ratio(hist0, hist1, myhist);
1078
1079 if (LinkInfo.TString::EndsWith("/") == false)
1080 {
1081 TString specialterm = LinkInfo(LinkInfo.Last('/') + 1, LinkInfo.Length() - LinkInfo.Last('/') - 1);
1082 if (specialterm.Contains("VAL") == false && specialterm.Contains("ERR") == false)
1083 specialterm = "VALERR";
1084
1085 if (specialterm.Contains("VAL") == false)
1086 {
1087 for (int i = 0; i < myhist->GetXaxis()->GetNbins(); i++)
1088 myhist->SetBinContent(i + 1, 1);
1089 }
1090
1091 if (specialterm.Contains("ERR") == false)
1092 {
1093 for (int i = 0; i < myhist->GetXaxis()->GetNbins(); i++)
1094 myhist->SetBinError(i + 1, 0);
1095 }
1096
1097 if (specialterm.Contains("TOPERR"))
1098 {
1099 for (int i = 0; i < hist1->GetXaxis()->GetNbins(); i++)
1100 hist1->SetBinError(i + 1, 0);
1101 histtool->Ratio(hist0, hist1, myhist);
1102 }
1103
1104 if (specialterm.Contains("BOTTOMERR"))
1105 {
1106 for (int i = 0; i < hist0->GetXaxis()->GetNbins(); i++)
1107 hist0->SetBinError(i + 1, 0);
1108 histtool->Ratio(hist0, hist1, myhist);
1109 }
1110 }
1111
1112 delete hist0;
1113 if (hist0 != hist1)
1114 delete hist1;
1115 }
1116
1117 if (LinkMode.TString::EqualTo("PULL"))
1118 {
1119 // This needs two object
1120 if (LinkObject.size() != 2)
1121 {
1122 MSGUser()->MSG_ERROR("PULL Link Needs two objects!!! FigureHist1D:", GetName().TString::Data(), " has ", LinkObject.size());
1123 return;
1124 }
1125
1126 if (!CheckLinkObjectType(2))
1127 return;
1128
1129 std::shared_ptr<HistTool> histtool = std::make_shared<HistTool>(MSGUser());
1130 auto hist0 = (TH1D *)(LinkHists[0]->Clone("TempPull0_" + GetName()));
1131 auto hist1 = (TH1D *)(LinkHists[1]->Clone("TempPull1_" + GetName()));
1132 myhist = (TH1D *)hist0->Clone(GetName().TString::Data());
1133 histtool->Pull(hist0, hist1, myhist);
1134
1135 if (LinkInfo.TString::EndsWith("/") == false)
1136 {
1137 TString specialterm = LinkInfo(LinkInfo.Last('/') + 1, LinkInfo.Length() - LinkInfo.Last('/') - 1);
1138 if (specialterm.Contains("VAL") == false && specialterm.Contains("ERR") == false)
1139 specialterm = "VALERR";
1140
1141 if (specialterm.Contains("VAL") == false)
1142 {
1143 for (int i = 0; i < myhist->GetXaxis()->GetNbins(); i++)
1144 myhist->SetBinContent(i + 1, 1);
1145 }
1146
1147 if (specialterm.Contains("ERR") == false)
1148 {
1149 for (int i = 0; i < myhist->GetXaxis()->GetNbins(); i++)
1150 myhist->SetBinError(i + 1, 0);
1151 }
1152
1153 if (specialterm.Contains("TOPERR"))
1154 {
1155 for (int i = 0; i < hist1->GetXaxis()->GetNbins(); i++)
1156 hist1->SetBinError(i + 1, 0);
1157 histtool->Pull(hist0, hist1, myhist);
1158 }
1159
1160 if (specialterm.Contains("BOTTOMERR"))
1161 {
1162 for (int i = 0; i < hist0->GetXaxis()->GetNbins(); i++)
1163 hist0->SetBinError(i + 1, 0);
1164 histtool->Pull(hist0, hist1, myhist);
1165 }
1166 }
1167
1168 delete hist0;
1169 delete hist1;
1170 }
1171
1172 if (LinkMode.TString::EqualTo("DELTA"))
1173 {
1174 // This needs two object
1175 if (LinkObject.size() != 2)
1176 {
1177 MSGUser()->MSG_ERROR("DELTA Link Needs two objects!!! FigureHist1D:", GetName().TString::Data(), " has ", LinkObject.size());
1178 return;
1179 }
1180
1181 if (!CheckLinkObjectType(2))
1182 return;
1183
1184 std::shared_ptr<HistTool> histtool = std::make_shared<HistTool>(MSGUser());
1185 auto hist0 = (TH1D *)(LinkHists[0]->Clone("TempDelta0_" + GetName()));
1186 auto hist1 = (TH1D *)(LinkHists[1]->Clone("TempDelta1_" + GetName()));
1187 myhist = (TH1D *)hist0->Clone(GetName().TString::Data());
1188 histtool->Delta(hist0, hist1, myhist);
1189
1190 if (LinkInfo.TString::EndsWith("/") == false)
1191 {
1192 TString specialterm = LinkInfo(LinkInfo.Last('/') + 1, LinkInfo.Length() - LinkInfo.Last('/') - 1);
1193 if (specialterm.Contains("VAL") == false && specialterm.Contains("ERR") == false)
1194 specialterm = "VALERR";
1195
1196 if (specialterm.Contains("VAL") == false)
1197 {
1198 for (int i = 0; i < myhist->GetXaxis()->GetNbins(); i++)
1199 myhist->SetBinContent(i + 1, 1);
1200 }
1201
1202 if (specialterm.Contains("ERR") == false)
1203 {
1204 for (int i = 0; i < myhist->GetXaxis()->GetNbins(); i++)
1205 myhist->SetBinError(i + 1, 0);
1206 }
1207
1208 if (specialterm.Contains("TOPERR"))
1209 {
1210 for (int i = 0; i < hist1->GetXaxis()->GetNbins(); i++)
1211 hist1->SetBinError(i + 1, 0);
1212 histtool->Delta(hist0, hist1, myhist);
1213 }
1214
1215 if (specialterm.Contains("BOTTOMERR"))
1216 {
1217 for (int i = 0; i < hist0->GetXaxis()->GetNbins(); i++)
1218 hist0->SetBinError(i + 1, 0);
1219 histtool->Delta(hist0, hist1, myhist);
1220 }
1221 }
1222
1223 delete hist0;
1224 delete hist1;
1225 }
1226
1227 if (LinkMode.TString::EqualTo("CHI2"))
1228 {
1229 // This needs two object
1230 if (LinkObject.size() != 2)
1231 {
1232 MSGUser()->MSG_ERROR("CHI2 Link Needs two objects!!! FigureHist1D:", GetName().TString::Data(), " has ", LinkObject.size());
1233 return;
1234 }
1235
1236 if (!CheckLinkObjectType(2))
1237 return;
1238
1239 std::shared_ptr<HistTool> histtool = std::make_shared<HistTool>(MSGUser());
1240 auto hist0 = (TH1D *)(LinkHists[0]->Clone("TempChi20_" + GetName()));
1241 auto hist1 = (TH1D *)(LinkHists[1]->Clone("TempChi21_" + GetName()));
1242 myhist = (TH1D *)hist0->Clone(GetName().TString::Data());
1243 histtool->Chi2(hist0, hist1, myhist);
1244
1245 if (LinkInfo.TString::EndsWith("/") == false)
1246 {
1247 TString specialterm = LinkInfo(LinkInfo.Last('/') + 1, LinkInfo.Length() - LinkInfo.Last('/') - 1);
1248 if (specialterm.Contains("VAL") == false && specialterm.Contains("ERR") == false)
1249 specialterm = "VALERR";
1250
1251 if (specialterm.Contains("VAL") == false)
1252 {
1253 for (int i = 0; i < myhist->GetXaxis()->GetNbins(); i++)
1254 myhist->SetBinContent(i + 1, 1);
1255 }
1256
1257 if (specialterm.Contains("ERR") == false)
1258 {
1259 for (int i = 0; i < myhist->GetXaxis()->GetNbins(); i++)
1260 myhist->SetBinError(i + 1, 0);
1261 }
1262
1263 if (specialterm.Contains("TOPERR"))
1264 {
1265 for (int i = 0; i < hist1->GetXaxis()->GetNbins(); i++)
1266 hist1->SetBinError(i + 1, 0);
1267 histtool->Chi2(hist0, hist1, myhist);
1268 }
1269
1270 if (specialterm.Contains("BOTTOMERR"))
1271 {
1272 for (int i = 0; i < hist0->GetXaxis()->GetNbins(); i++)
1273 hist0->SetBinError(i + 1, 0);
1274 histtool->Chi2(hist0, hist1, myhist);
1275 }
1276 }
1277
1278 delete hist0;
1279 delete hist1;
1280 }
1281}
1282
1283std::pair<double, double> FigureHist1D::GetMinAndMax(double xmin, double xmax)
1284{
1285 if (FromHistLink == true && myhist == nullptr)
1287
1288 double ymin, ymax;
1289 int count = 0;
1290
1291 for (int i = 1; i <= myhist->GetNbinsX(); i++)
1292 {
1293 if (myhist->GetBinLowEdge(i) < xmin)
1294 continue;
1295 if (myhist->GetBinLowEdge(i) + myhist->GetBinWidth(i) > xmax)
1296 continue;
1297
1298 if (count == 0)
1299 {
1300 ymin = myhist->GetBinContent(i) - myhist->GetBinError(i);
1301 ymax = myhist->GetBinContent(i) + myhist->GetBinError(i);
1302 }
1303 else
1304 {
1305 if (ymin > myhist->GetBinContent(i) - myhist->GetBinError(i))
1306 ymin = myhist->GetBinContent(i) - myhist->GetBinError(i);
1307 if (ymax < myhist->GetBinContent(i) + myhist->GetBinError(i))
1308 ymax = myhist->GetBinContent(i) + myhist->GetBinError(i);
1309 }
1310
1311 ++count;
1312 }
1313
1314 return std::pair<double, double>(ymin, ymax);
1315}
1316
1317void FigureHist1D::Scale(double factor)
1318{
1319 if (FromHistLink && myhist == nullptr)
1321
1322 myhist->Scale(factor);
1323}
1324
1326{
1327 if (FromHistLink && myhist == nullptr)
1329
1330 myhist->Rebin(num);
1331}
1332
1333// Functions for FigureHStack
1334FigureHStack::FigureHStack(std::shared_ptr<MSGTool> MSG, std::shared_ptr<FigureStyleHelper> shelper, const TString &elementname, const std::vector<TString> &linkhists, const TString &option, FigureElement *mother)
1335 : FigureElement(MSG, shelper, elementname, "FigureHStack", mother)
1336{
1337 this->LinkedHists = linkhists;
1338 this->DrawOption = option;
1339 myhstack = new THStack(elementname, "");
1340
1341 if (linkhists.size() == 0)
1342 MSGUser()->MSG_ERROR("you should link at least one hist to hstack");
1343}
1344
1346{
1347 auto titleguard = MSGUser()->StartTitleWithGuard("FigureHStack::SetStyle");
1348
1349 for (auto &name : LinkedHists)
1350 {
1351 auto obj = TraceElement(name);
1352 if (obj == nullptr)
1353 {
1354 MSGUser()->MSG_WARNING("input element ", name, " does not exist, will be ignored");
1355 continue;
1356 }
1357
1358 if (obj->GetTypeName() != "FigureHist1D")
1359 {
1360 MSGUser()->MSG_WARNING("input element ", name, " does not belong to FigureHist1D, will be ignored");
1361 continue;
1362 }
1363
1364 std::shared_ptr<FigureHist1D> hist = std::dynamic_pointer_cast<FigureHist1D>(obj);
1365 if (hist->FromHistLink == true && hist->myhist == nullptr)
1366 hist->CreateHistFromHistLink();
1367
1368 myhstack->Add(hist->GetHist());
1369 hist->ForHStack = true;
1370 }
1371}
1372
1374{
1375 auto titleguard = MSGUser()->StartTitleWithGuard("FigureHStack::DrawElement");
1376 int count = 0;
1377 for (auto &name : LinkedHists)
1378 {
1379 auto obj = TraceElement(name);
1380 if (obj == nullptr)
1381 {
1382 MSGUser()->MSG_WARNING("input element ", name, " does not exist, will be ignored");
1383 continue;
1384 }
1385
1386 if (obj->GetTypeName() != "FigureHist1D")
1387 {
1388 MSGUser()->MSG_WARNING("input element ", name, " does not belong to FigureHist1D, will be ignored");
1389 continue;
1390 }
1391
1392 std::shared_ptr<FigureHist1D> hist = std::dynamic_pointer_cast<FigureHist1D>(obj);
1393 if (hist->FromHistLink == true && hist->myhist == nullptr)
1394 hist->CreateHistFromHistLink();
1395
1396 if (count == 0)
1397 {
1398 empty_hist = (TH1D *)(hist->GetHist()->Clone("empty_hist"));
1399 empty_hist->SetDirectory(0);
1400 empty_hist->SetStats(0);
1401 empty_hist->SetTitle("");
1402 empty_hist->Reset("ICESM");
1403
1404 empty_hist->Draw();
1405 }
1406
1407 ++count;
1408 }
1409
1410 myhstack->Draw(DrawOption + " same");
1411
1412 if (draw_total_hist)
1413 {
1414 GetTotalHist();
1416 total_hist->SetTitle("");
1417 total_hist->SetStats(0);
1419 }
1420}
1421
1425void FigureHStack::DrawTotalHist(const TString &option, std::function<void(TH1D *)> optionfunc)
1426{
1427 draw_total_hist = true;
1428 total_hist_drawoption = option + " same";
1429 total_hist_optionfunc = optionfunc;
1430}
1431
1433{
1435 return total_hist;
1436}
1437
1439{
1440 if (total_hist)
1441 return;
1442
1443 int count = 0;
1444 for (auto &name : LinkedHists)
1445 {
1446 auto obj = TraceElement(name);
1447 if (obj == nullptr)
1448 {
1449 MSGUser()->MSG_WARNING("input element ", name, " does not exist, will be ignored");
1450 continue;
1451 }
1452
1453 if (obj->GetTypeName() != "FigureHist1D")
1454 {
1455 MSGUser()->MSG_WARNING("input element ", name, " does not belong to FigureHist1D, will be ignored");
1456 continue;
1457 }
1458
1459 std::shared_ptr<FigureHist1D> hist = std::dynamic_pointer_cast<FigureHist1D>(obj);
1460 if (hist->FromHistLink == true && hist->myhist == nullptr)
1461 hist->CreateHistFromHistLink();
1462
1463 if (count == 0)
1464 {
1465 total_hist = (TH1D *)(hist->GetHist()->Clone("total_hist"));
1466 total_hist->SetDirectory(0);
1467 // total_hist->Sumw2();
1468 }
1469 else
1470 {
1471 total_hist->Add(hist->GetHist());
1472 }
1473
1474 ++count;
1475 }
1476}
1477
1478std::pair<double, double> FigureHStack::GetMinAndMax(double xmin, double xmax)
1479{
1481 double ymin, ymax;
1482 int count = 0;
1483
1484 for (int i = 1; i <= total_hist->GetNbinsX(); i++)
1485 {
1486 if (total_hist->GetBinLowEdge(i) < xmin)
1487 continue;
1488 if (total_hist->GetBinLowEdge(i) + total_hist->GetBinWidth(i) > xmax)
1489 continue;
1490
1491 if (count == 0)
1492 {
1493 ymin = total_hist->GetBinContent(i) - total_hist->GetBinError(i);
1494 ymax = total_hist->GetBinContent(i) + total_hist->GetBinError(i);
1495 }
1496 else
1497 {
1498 if (ymin > total_hist->GetBinContent(i) - total_hist->GetBinError(i))
1499 ymin = total_hist->GetBinContent(i) - total_hist->GetBinError(i);
1500 if (ymax < total_hist->GetBinContent(i) + total_hist->GetBinError(i))
1501 ymax = total_hist->GetBinContent(i) + total_hist->GetBinError(i);
1502 }
1503
1504 ++count;
1505 }
1506
1507 return std::pair<double, double>(ymin, ymax);
1508}
1509
1510void FigureHStack::Scale(double factor)
1511{
1512 auto titleguard = MSGUser()->StartTitleWithGuard("FigureHStack::Scale");
1513 for (auto &name : LinkedHists)
1514 {
1515 auto obj = TraceElement(name);
1516 if (obj == nullptr)
1517 {
1518 MSGUser()->MSG_WARNING("input element ", name, " does not exist, will be ignored");
1519 continue;
1520 }
1521
1522 if (obj->GetTypeName() != "FigureHist1D")
1523 {
1524 MSGUser()->MSG_WARNING("input element ", name, " does not belong to FigureHist1D, will be ignored");
1525 continue;
1526 }
1527
1528 std::shared_ptr<FigureHist1D> hist = std::dynamic_pointer_cast<FigureHist1D>(obj);
1529 hist->Scale(factor);
1530 }
1531
1532 if (total_hist)
1533 total_hist->Scale(factor);
1534}
1535
1537{
1538 auto titleguard = MSGUser()->StartTitleWithGuard("FigureHStack::Rebin");
1539 for (auto &name : LinkedHists)
1540 {
1541 auto obj = TraceElement(name);
1542 if (obj == nullptr)
1543 {
1544 MSGUser()->MSG_WARNING("input element ", name, " does not exist, will be ignored");
1545 continue;
1546 }
1547
1548 if (obj->GetTypeName() != "FigureHist1D")
1549 {
1550 MSGUser()->MSG_WARNING("input element ", name, " does not belong to FigureHist1D, will be ignored");
1551 continue;
1552 }
1553
1554 std::shared_ptr<FigureHist1D> hist = std::dynamic_pointer_cast<FigureHist1D>(obj);
1555 hist->Rebin(num);
1556 }
1557
1558 if (total_hist)
1559 total_hist->Rebin(num);
1560 if (empty_hist)
1561 empty_hist->Rebin(num);
1562}
1563
1565{
1566 delete myhstack;
1567 delete empty_hist;
1568 delete total_hist;
1569 delete total_hist_graph;
1570}
1571
1572// Functions for FigureGraph1D
1573
1574FigureGraph1D::FigureGraph1D(std::shared_ptr<MSGTool> MSG, std::shared_ptr<FigureStyleHelper> shelper, const TString &elementname, TGraph *graph, const TString &option, FigureElement *mother, std::function<void(TGraph *)> optionfunc)
1575 : FigureElement(MSG, shelper, elementname, "FigureGraph1D", mother)
1576{
1577 mygraph = (TGraph *)graph->Clone(TString::Format("Temp_%s", elementname.Data()));
1578 DrawOption = option;
1579 OptionFunc = optionfunc;
1580}
1581
1583{
1584 mygraph->Draw(DrawOption.TString::Data());
1585}
1586
1588{
1589 StyleUser()->SetGraph1DStyle(this);
1591}
1592
1593std::pair<double, double> FigureGraph1D::GetMinAndMax(double xmin, double xmax)
1594{
1595 double ymin, ymax;
1596 int count = 0;
1597
1598 for (int i = 0; i < mygraph->GetN(); i++)
1599 {
1600 auto xvalue = mygraph->GetPointX(i);
1601 auto xerrorup = mygraph->GetErrorXhigh(i);
1602 auto xerrordown = mygraph->GetErrorXlow(i);
1603
1604 auto yvalue = mygraph->GetPointY(i);
1605 auto yerrorup = mygraph->GetErrorYhigh(i);
1606 auto yerrordown = mygraph->GetErrorYlow(i);
1607
1608 // in case the graph has no error on points
1609 if (xerrorup == -1)
1610 {
1611 xerrorup = 0;
1612 xerrordown = 0;
1613 yerrorup = 0;
1614 yerrordown = 0;
1615 }
1616
1617 if (xvalue - xerrordown < xmin || xvalue + xerrorup > xmax)
1618 continue;
1619
1620 if (count == 0)
1621 {
1622 ymin = yvalue - yerrordown;
1623 ymax = yvalue + yerrorup;
1624 }
1625 else
1626 {
1627 if (ymin > yvalue - yerrordown)
1628 ymin = yvalue - yerrordown;
1629 if (ymax < yvalue + yerrorup)
1630 ymax = yvalue + yerrorup;
1631 }
1632
1633 ++count;
1634 }
1635
1636 return std::pair<double, double>(ymin, ymax);
1637}
1638
1640{
1641 delete mygraph;
1642}
1643
1644// Functions for FigureFunc1D
1645
1646FigureFunc1D::FigureFunc1D(std::shared_ptr<MSGTool> MSG, std::shared_ptr<FigureStyleHelper> shelper, const TString &elementname, TF1 *func, const TString &option, FigureElement *mother, std::function<void(TF1 *)> optionfunc)
1647 : FigureElement(MSG, shelper, elementname, "FigureFunc1D", mother)
1648{
1649 myfunc = (TF1 *)func->Clone(TString::Format("Temp_%s", elementname.Data()));
1650 DrawOption = option;
1651 OptionFunc = optionfunc;
1652}
1653
1655{
1656 myfunc->Draw(DrawOption.TString::Data());
1657}
1658
1660{
1661 StyleUser()->SetFunc1DStyle(this);
1663}
1664
1665std::pair<double, double> FigureFunc1D::GetMinAndMax(double xmin, double xmax)
1666{
1667 return std::pair<double, double>(myfunc->GetMinimum(xmin, xmax), myfunc->GetMaximum(xmin, xmax));
1668}
1669
1671{
1672 delete myfunc;
1673}
1674
1675// Functions for FigureHist2D
1676FigureHist2D::FigureHist2D(std::shared_ptr<MSGTool> MSG, std::shared_ptr<FigureStyleHelper> shelper, const TString &elementname, TH2D *hist, const TString &option, FigureElement *mother, std::function<void(TH2D *)> optionfunc)
1677 : FigureElement(MSG, shelper, elementname, "FigureHist2D", mother)
1678{
1679 myhist = (TH2D *)hist->Clone(TString::Format("Temp_%s", elementname.Data()));
1680 DrawOption = option;
1681 OptionFunc = optionfunc;
1682}
1683
1685{
1686 delete myhist;
1687}
1688
1689void FigureHist2D::Rebin(int rebinnumx, int rebinnumy)
1690{
1691 myhist->RebinX(rebinnumx);
1692 myhist->RebinY(rebinnumy);
1693}
1694
1695void FigureHist2D::Scale(double factor)
1696{
1697 myhist->Scale(factor);
1698}
1699
1704
1706{
1707 StyleUser()->SetHist2DStyle(this);
1709}
1710
1711// Functions for FigureLatex
1712
1713FigureLatex::FigureLatex(std::shared_ptr<MSGTool> MSG, std::shared_ptr<FigureStyleHelper> shelper,
1714 const TString &content, double posx, double poxy, Color_t color, FigureElement *mother, std::function<void(TLatex *)> optionfunc)
1715 : FigureElement(MSG, shelper, content, "FigureLatex", mother)
1716{
1717 mylatex = new TLatex(posx, poxy, content.TString::Data());
1718 mylatex->SetTextColor(color);
1719 mylatex->SetNDC();
1720 OptionFunc = optionfunc;
1721}
1722
1724{
1725 delete mylatex;
1726}
1727
1729{
1730 mylatex->AppendPad();
1731}
1732
1734{
1735 StyleUser()->SetLatexStyle(this);
1737}
1738
1739// Functions for FigurePad
1740
1741FigurePad::FigurePad(std::shared_ptr<MSGTool> MSG, std::shared_ptr<FigureStyleHelper> shelper, const TString &elementname, int lbx, int lby, int rtx, int rty, FigureElement *mother, std::function<void(TPad *)> optionfunc)
1742 : FigureElement(MSG, shelper, elementname, "FigurePad", mother)
1743{
1744 mypad = new TPad(elementname.TString::Data(), elementname.TString::Data(),
1745 (double)(lbx - mother->Range_Total.LB_X) / (mother->Range_Total.RT_X - mother->Range_Total.LB_X),
1746 (double)(lby - mother->Range_Total.LB_Y) / (mother->Range_Total.RT_Y - mother->Range_Total.LB_Y),
1747 (double)(rtx - mother->Range_Total.LB_X) / (mother->Range_Total.RT_X - mother->Range_Total.LB_X),
1748 (double)(rty - mother->Range_Total.LB_Y) / (mother->Range_Total.RT_Y - mother->Range_Total.LB_Y));
1749 OptionFunc = optionfunc;
1750
1751 Range_Total.LB_X = lbx;
1752 Range_Total.LB_Y = lby;
1753 Range_Total.RT_X = rtx;
1754 Range_Total.RT_Y = rty;
1755
1756 Range_vec.push_back(Range_Total);
1757}
1758
1760{
1761 mypad->Draw();
1762 // Make sure the linked objects are drew under this pad
1763 mypad->cd();
1764}
1765
1767{
1768 StyleUser()->SetPadStyle(this);
1769 OptionFunc(this->GetPad());
1770
1771 // draw the legend
1772 if (plot_legend)
1773 {
1774 // add entries
1775 std::deque<std::shared_ptr<FigureElement>> v_legend_elements;
1776 if (legend_entries.size() == 0)
1777 {
1778 v_legend_elements = LinkedElement;
1779 legend_options = std::vector<TString>(v_legend_elements.size(), "lpfe");
1780 }
1781 else
1782 {
1783 int i = 0;
1784 for (auto &entry : legend_entries)
1785 {
1786 for (auto &elem : LinkedElement)
1787 if (elem->GetName() == entry)
1788 v_legend_elements.emplace_back(elem);
1789
1790 ++i;
1791
1792 if (i != v_legend_elements.size())
1793 MSGUser()->MSG_WARNING("Given legend entry ", entry, " does not exist in the linked objects");
1794 }
1795 }
1796
1797 for (int i = 0; i < v_legend_elements.size(); ++i)
1798 {
1799 auto elem = v_legend_elements.at(i);
1800 auto elem_option = legend_options.at(i);
1801 if (elem->IsType("FigureHist1D"))
1802 {
1803 auto hist = std::dynamic_pointer_cast<FigureHist1D>(elem);
1804 if (!hist->DrawAsTGraph)
1805 legend->AddEntry(hist->GetHist(), elem->GetName(), elem_option);
1806 else
1807 legend->AddEntry(hist->mygraph, elem->GetName(), elem_option);
1808 }
1809 if (elem->IsType("FigureGraph1D"))
1810 legend->AddEntry((std::dynamic_pointer_cast<FigureGraph1D>(elem))->GetGraph(), elem->GetName(), elem_option);
1811 if (elem->IsType("FigureFunc1D"))
1812 legend->AddEntry((std::dynamic_pointer_cast<FigureFunc1D>(elem))->GetFunc(), elem->GetName(), elem_option);
1813 if (elem->IsType("FigureHist2D"))
1814 legend->AddEntry((std::dynamic_pointer_cast<FigureHist2D>(elem))->GetHist(), elem->GetName(), elem_option);
1815 if (elem->IsType("FigureHStack"))
1816 {
1817 auto hstack = std::dynamic_pointer_cast<FigureHStack>(elem);
1818 if (hstack->draw_total_hist)
1819 legend->AddEntry((std::dynamic_pointer_cast<FigureHStack>(elem))->GetTotalHist(), elem->GetName(), elem_option);
1820 }
1821 }
1822
1823 if (legend_header.BeginsWith("ATLAS"))
1824 {
1825 // draw "ATLAS" slanted
1826 TLatex *atlas_text = new TLatex(legend->GetX1(), legend->GetY2() - 0.03, "ATLAS");
1827 atlas_text->SetNDC();
1828 atlas_text->SetTextFont(72);
1829 atlas_text->SetTextSize(StyleUser()->LEGEND_TEXT_SIZE_PERCENT);
1830 atlas_text->SetTextColor(1);
1831 atlas_text->AppendPad();
1832
1833 TString rest_info = legend_header(5, legend_header.Length());
1834 TLatex rest_text;
1835 rest_text.SetNDC();
1836 rest_text.SetTextFont(42);
1837 rest_text.SetTextSize(StyleUser()->LEGEND_TEXT_SIZE_PERCENT);
1838 rest_text.SetTextColor(1);
1839 rest_text.DrawLatex(legend->GetX1() + 1.6 * StyleUser()->LEGEND_TEXT_SIZE_PERCENT * 696 * GetPad()->GetWh() / (472 * GetPad()->GetWw()), legend->GetY2() - 0.03, rest_info.Data());
1840
1841 legend->SetHeader("", "");
1842 }
1843 else if (legend_header != "")
1844 {
1846 }
1847 legend->SetNColumns(legend_column);
1848
1849 legend->Draw("same");
1850 }
1851
1852 mypad->Update();
1853 mypad->RedrawAxis();
1854}
1855
1857{
1858 mypad->cd();
1859}
1860
1862{
1863 // delete mypad;
1864}
1865
1874std::shared_ptr<FigurePad> FigurePad::BookPad(const TString &padname, int lbx, int lby, int rtx, int rty, std::function<void(TPad *)> optionfunc)
1875{
1876 if (!CheckDuplicate(padname))
1877 return nullptr;
1878
1879 auto newpad = std::shared_ptr<FigurePad>(new FigurePad(MSGUser(), StyleUser(), padname, lbx, lby, rtx, rty, this, optionfunc));
1880 if (Contain(newpad) == false)
1881 MSGUser()->MSG_ERROR("New Pad ", padname.TString::Data(), " is not within the Canvas ", GetName().TString::Data());
1882 MapLinkedElement.emplace(padname, LinkedElement.size());
1883 LinkedElement.emplace_back(newpad);
1884 return newpad;
1885}
1886
1893std::shared_ptr<FigureHist1D> FigurePad::SetInputHist1D(const TString &elementname, TH1D *hist, const TString &option, std::function<void(TH1D *)> optionfunc)
1894{
1895 if (!CheckDuplicate(elementname))
1896 return nullptr;
1897
1898 TString newoption = option;
1899 // if (waitforfirstlink == false)
1900 newoption = option + " same";
1901 auto newhist = std::shared_ptr<FigureHist1D>(new FigureHist1D(MSGUser(), StyleUser(), elementname, hist, newoption, this, optionfunc));
1902 MapLinkedElement.emplace(elementname, LinkedElement.size());
1903 LinkedElement.emplace_back(newhist);
1904 // waitforfirstlink = false;
1905 newhist->index_in_pad = n_colored_objects;
1907
1908 return newhist;
1909}
1910
1920std::shared_ptr<FigureHist1D> FigurePad::SetInputHist1D(const TString &elementname, const TString &linkinfo, const TString &option, std::function<void(TH1D *)> optionfunc)
1921{
1922 if (!CheckDuplicate(elementname))
1923 return nullptr;
1924
1925 TString newoption = option;
1926 // if (waitforfirstlink == false)
1927 newoption = option + " same";
1928 auto newhist = std::shared_ptr<FigureHist1D>(new FigureHist1D(MSGUser(), StyleUser(), elementname, linkinfo, newoption, this, optionfunc));
1929 MapLinkedElement.emplace(elementname, LinkedElement.size());
1930 LinkedElement.emplace_back(newhist);
1931 // waitforfirstlink = false;
1932 newhist->index_in_pad = n_colored_objects;
1934
1935 return newhist;
1936}
1937
1944std::shared_ptr<FigureHist1D> FigurePad::SetInputHist1DGraph(const TString &elementname, TH1D *hist, const TString &option, std::function<void(TGraph *)> optionfunc)
1945{
1946 if (!CheckDuplicate(elementname))
1947 return nullptr;
1948
1949 TString newoption = option;
1950 // if (waitforfirstlink == false)
1951 newoption = option + " same";
1952 auto newhist = std::shared_ptr<FigureHist1D>(new FigureHist1D(MSGUser(), StyleUser(), elementname, hist, newoption, this, optionfunc));
1953 MapLinkedElement.emplace(elementname, LinkedElement.size());
1954 LinkedElement.emplace_back(newhist);
1955 // waitforfirstlink = false;
1956 newhist->index_in_pad = n_colored_objects;
1958
1959 return newhist;
1960}
1961
1971std::shared_ptr<FigureHist1D> FigurePad::SetInputHist1DGraph(const TString &elementname, const TString &linkinfo, const TString &option, std::function<void(TGraph *)> optionfunc)
1972{
1973 if (!CheckDuplicate(elementname))
1974 return nullptr;
1975
1976 TString newoption = option;
1977 // if (waitforfirstlink == false)
1978 newoption = option + " same";
1979 auto newhist = std::shared_ptr<FigureHist1D>(new FigureHist1D(MSGUser(), StyleUser(), elementname, linkinfo, newoption, this, optionfunc));
1980 MapLinkedElement.emplace(elementname, LinkedElement.size());
1981 LinkedElement.emplace_back(newhist);
1982 // waitforfirstlink = false;
1983 newhist->index_in_pad = n_colored_objects;
1985
1986 return newhist;
1987}
1988
1994std::shared_ptr<FigureHStack> FigurePad::SetHStack(const TString &elementname, const std::vector<TString> &linkinfo, const TString &option)
1995{
1996 if (!CheckDuplicate(elementname))
1997 return nullptr;
1998
1999 auto titleguard = MSGUser()->StartTitleWithGuard("FigurePad::SetHStack");
2000 if (hashstack)
2001 {
2002 MSGUser()->MSG_WARNING("THStack for this pad has already existed");
2003 return nullptr;
2004 }
2005 else
2006 {
2007 auto newhstack = std::shared_ptr<FigureHStack>(new FigureHStack(MSGUser(), StyleUser(), elementname, linkinfo, option, this));
2008 LinkedElement.emplace_front(newhstack);
2009 for (auto &iter : MapLinkedElement)
2010 iter.second += 1;
2011 MapLinkedElement.emplace(elementname, 0);
2012
2013 return newhstack;
2014 }
2015}
2016
2023std::shared_ptr<FigureGraph1D> FigurePad::SetInputGraph1D(const TString &elementname, TGraph *graph, const TString &option, std::function<void(TGraph *)> optionfunc)
2024{
2025 if (!CheckDuplicate(elementname))
2026 return nullptr;
2027
2028 TString newoption = option;
2029 // if (waitforfirstlink == false)
2030 newoption = option + " same";
2031 auto newgraph = std::shared_ptr<FigureGraph1D>(new FigureGraph1D(MSGUser(), StyleUser(), elementname, graph, newoption, this, optionfunc));
2032
2033 MapLinkedElement.emplace(elementname, LinkedElement.size());
2034 LinkedElement.emplace_back(newgraph);
2035 // waitforfirstlink = false;
2036 newgraph->index_in_pad = n_colored_objects;
2038
2039 return newgraph;
2040}
2041
2048std::shared_ptr<FigureFunc1D> FigurePad::SetInputFunc1D(const TString &elementname, TF1 *func, const TString &option, std::function<void(TF1 *)> optionfunc)
2049{
2050 if (!CheckDuplicate(elementname))
2051 return nullptr;
2052
2053 TString newoption = option;
2054 // if (waitforfirstlink == false)
2055 newoption = option + " same";
2056 auto newfunc = std::shared_ptr<FigureFunc1D>(new FigureFunc1D(MSGUser(), StyleUser(), elementname, func, newoption, this, optionfunc));
2057
2058 MapLinkedElement.emplace(elementname, LinkedElement.size());
2059 LinkedElement.emplace_back(newfunc);
2060 // waitforfirstlink = false;
2061 newfunc->index_in_pad = n_colored_objects;
2063
2064 return newfunc;
2065}
2066
2073std::shared_ptr<FigureHist2D> FigurePad::SetInputHist2D(const TString &elementname, TH2D *hist, const TString &option, std::function<void(TH2D *)> optionfunc)
2074{
2075 if (!CheckDuplicate(elementname))
2076 return nullptr;
2077
2078 TString newoption = option;
2079 // if (waitforfirstlink == false)
2080 newoption = option + " same";
2081 auto newhist = std::shared_ptr<FigureHist2D>(new FigureHist2D(MSGUser(), StyleUser(), elementname, hist, newoption, this, optionfunc));
2082 MapLinkedElement.emplace(elementname, LinkedElement.size());
2083 LinkedElement.emplace_back(newhist);
2084 // waitforfirstlink = false;
2085 newhist->index_in_pad = n_colored_objects;
2087
2088 return newhist;
2089}
2090
2097void FigurePad::SetLatex(const TString &content, double posx, double poxy, Color_t color, std::function<void(TLatex *)> optionfunc)
2098{
2099 if (!CheckDuplicate(content))
2100 return;
2101
2102 auto newlatex = std::shared_ptr<FigureLatex>(new FigureLatex(MSGUser(), StyleUser(), content, posx, poxy, color, this, optionfunc));
2103 MapLinkedElement.emplace(content, LinkedElement.size());
2104 LinkedElement.emplace_back(newlatex);
2105}
2106
2113void FigurePad::DrawATLASLabel(const TString &content, double posx, double posy, Color_t color, double space)
2114{
2115 SetLatex("ATLAS", posx, posy, color, [](TLatex *latex)
2116 { latex->SetTextFont(72); });
2117
2118 if (space <= 0)
2119 SetLatex(content, posx + 1.6 * StyleUser()->LEGEND_TEXT_SIZE_PERCENT * 696 * GetPad()->GetWh() / (472 * GetPad()->GetWw()), posy, color);
2120 else
2121 SetLatex(content, posx + space, posy, color);
2122}
2123
2129void FigurePad::Norm(const TString &elemname1, const TString &elemname2, double xmin, double xmax)
2130{
2131 // norm the integral of elem1 to elem2
2132 auto elem1 = FindLinkElement(elemname1);
2133 auto elem2 = FindLinkElement(elemname2);
2134
2135 TH1D *h1 = nullptr;
2136 TH1D *h2 = nullptr;
2137
2138 if (elem1->IsType("FigureHist1D") && elem2->IsType("FigureHist1D"))
2139 {
2140 h1 = (std::dynamic_pointer_cast<FigureHist1D>(elem1))->GetHist();
2141 h2 = (std::dynamic_pointer_cast<FigureHist1D>(elem2))->GetHist();
2142 }
2143 else if (elem1->IsType("FigureHStack") && elem2->IsType("FigureHist1D"))
2144 {
2145 h1 = (std::dynamic_pointer_cast<FigureHStack>(elem1))->GetTotalHist();
2146 h2 = (std::dynamic_pointer_cast<FigureHist1D>(elem2))->GetHist();
2147 }
2148 else if (elem1->IsType("FigureHist1D") && elem2->IsType("FigureHStack"))
2149 {
2150 h1 = (std::dynamic_pointer_cast<FigureHist1D>(elem1))->GetHist();
2151 h2 = (std::dynamic_pointer_cast<FigureHStack>(elem2))->GetTotalHist();
2152 }
2153 else
2154 {
2155 auto titleguard = MSGUser()->StartTitleWithGuard("FigurePad::Norm");
2156 MSGUser()->MSG_WARNING("can only norm element with type FigureHist1D or FigureHStack");
2157 return;
2158 }
2159
2160 double factor;
2161 if (xmin == xmax && xmin == 0)
2162 {
2163 factor = h2->Integral() / h1->Integral();
2164 }
2165 else
2166 {
2167 int bin1 = h1->FindBin(xmin);
2168 int bin2 = h1->FindBin(xmax);
2169
2170 factor = h2->Integral(bin1, bin2) / h1->Integral(bin1, bin2);
2171 }
2172
2173 if (elem1->IsType("FigureHist1D"))
2174 std::dynamic_pointer_cast<FigureHist1D>(elem1)->Scale(factor);
2175 if (elem1->IsType("FigureHStack"))
2176 std::dynamic_pointer_cast<FigureHStack>(elem1)->Scale(factor);
2177}
2178
2182void FigurePad::SetLegend(const TString &header, const TString &option)
2183{
2184 plot_legend = true;
2185 legend = new TLegend();
2186 legend_header = header;
2187 legend_header_option = option;
2188}
2189
2197void FigurePad::SetLegend(const TString &header, const TString &option, double xmin, double ymin, double xmax, double ymax)
2198{
2199 plot_legend = true;
2200 legend = new TLegend();
2201 legend_header = header;
2202 legend_header_option = option;
2204 legend_xmin = xmin;
2205 legend_xmax = xmax;
2206 legend_ymin = ymin;
2207 legend_ymax = ymax;
2208}
2209
2213{
2214 legend_column = column;
2215}
2216
2220void FigurePad::SetLegendEntries(const std::vector<TString> &entries, const std::vector<TString> &options)
2221{
2222 if (entries.size() != options.size())
2223 {
2224 MSGUser()->MSG_WARNING("entries and options must have the same size");
2225 return;
2226 }
2227 legend_entries = entries;
2228 legend_options = options;
2229}
2230
2232void FigurePad::SetGridx(bool grid)
2233{
2234 if (grid)
2235 mypad->SetGridx(1);
2236 else
2237 mypad->SetGridx(0);
2238}
2239
2241void FigurePad::SetGridy(bool grid)
2242{
2243 if (grid)
2244 mypad->SetGridy(1);
2245 else
2246 mypad->SetGridy(0);
2247}
2248
2250void FigurePad::SetLogx(int value)
2251{
2252 mypad->SetLogx(value);
2253}
2254
2256void FigurePad::SetLogy(int value)
2257{
2258 mypad->SetLogy(value);
2259}
2260
2262void FigurePad::SetLogz(int value)
2263{
2264 mypad->SetLogz(value);
2265}
2266
2270void FigurePad::SetXaxisRange(double min, double max)
2271{
2272 user_set_rangex = true;
2273 max_xaxis = max;
2274 min_xaxis = min;
2275}
2276
2280void FigurePad::SetYaxisRange(double min, double max)
2281{
2282 user_set_rangey = true;
2283 max_yaxis = max;
2284 min_yaxis = min;
2285}
2286
2290void FigurePad::SetZaxisRange(double min, double max)
2291{
2292 user_set_rangez = true;
2293 max_zaxis = max;
2294 min_zaxis = min;
2295}
2296
2297// Functions for FigureCanvas
2298
2299FigureCanvas::FigureCanvas(std::shared_ptr<MSGTool> MSG, std::shared_ptr<FigureStyleHelper> shelper, const TString &elementname, int npx, int npy)
2300 : FigureElement(MSG, shelper, elementname, "FigureCanvas", nullptr)
2301{
2302 mycanvas = new TCanvas(elementname.TString::Data(), elementname.TString::Data(), npx, npy);
2303
2304 Range_Total.LB_X = 0;
2305 Range_Total.LB_Y = 0;
2306 Range_Total.RT_X = npx;
2307 Range_Total.RT_Y = npy;
2308
2309 Range_vec.push_back(Range_Total);
2310}
2311
2313{
2314 delete mycanvas;
2315}
2316
2318{
2319 mycanvas->Draw();
2320 mycanvas->cd();
2321 // Make sure thew linked objects are drew under this canvas
2322}
2323
2325{
2326 mycanvas->cd();
2327}
2328
2337std::shared_ptr<FigurePad> FigureCanvas::BookPad(const TString &padname, int lbx, int lby, int rtx, int rty, std::function<void(TPad *)> optionfunc)
2338{
2339 if (!CheckDuplicate(padname))
2340 return nullptr;
2341
2342 auto newpad = std::shared_ptr<FigurePad>(new FigurePad(MSGUser(), StyleUser(), padname, lbx, lby, rtx, rty, this, optionfunc));
2343 if (Contain(newpad) == false)
2344 MSGUser()->MSG_ERROR("New Pad ", padname.TString::Data(), " is not within the Canvas ", GetName().TString::Data());
2345 MapLinkedElement.emplace(padname, LinkedElement.size());
2346 LinkedElement.emplace_back(newpad);
2347 return newpad;
2348}
2349
2358std::shared_ptr<FigurePad> FigureCanvas::BookPadNDC(const TString &padname, double lbx, double lby, double rtx, double rty, std::function<void(TPad *)> optionfunc)
2359{
2360 if (!CheckDuplicate(padname))
2361 return nullptr;
2362
2363 int newlbx = lbx * (this->Range_Total.RT_X - this->Range_Total.LB_X) + this->Range_Total.LB_X;
2364 int newlby = lby * (this->Range_Total.RT_Y - this->Range_Total.LB_Y) + this->Range_Total.LB_Y;
2365 int newrtx = rtx * (this->Range_Total.RT_X - this->Range_Total.LB_X) + this->Range_Total.LB_X;
2366 int newrty = rty * (this->Range_Total.RT_Y - this->Range_Total.LB_Y) + this->Range_Total.LB_Y;
2367
2368 auto newpad = std::shared_ptr<FigurePad>(new FigurePad(MSGUser(), StyleUser(), padname, newlbx, newlby, newrtx, newrty, this, optionfunc));
2369 if (Contain(newpad) == false)
2370 MSGUser()->MSG_ERROR("New Pad ", padname.TString::Data(), " is not within the Canvas ", GetName().TString::Data());
2371 MapLinkedElement.emplace(padname, LinkedElement.size());
2372 LinkedElement.emplace_back(newpad);
2373 return newpad;
2374}
2375
2376// Functions for FigureTool
2377
2380FigureTool::FigureTool(std::shared_ptr<MSGTool> MSG) : Tool(MSG)
2381{
2382 stylehelper = std::make_shared<FigureStyleHelper>(MSG);
2383}
2384
2388FigureTool::FigureTool(std::shared_ptr<MSGTool> MSG, std::shared_ptr<FigureStyleHelper> shelper) : Tool(MSG)
2389{
2390 stylehelper = shelper;
2391}
2392
2398std::shared_ptr<FigureCanvas> FigureTool::BookFigure(const TString &figurename, int size_x, int size_y)
2399{
2400 auto newfigure = std::shared_ptr<FigureCanvas>(new FigureCanvas(MSGUser(), stylehelper, figurename, size_x, size_y));
2401 BookedFigure.emplace(figurename, newfigure);
2402 return newfigure;
2403}
2404
2408std::shared_ptr<FigureCanvas> FigureTool::BookATLASSquare(const TString &figurename)
2409{
2410 return BookFigure(figurename, 600, 600);
2411}
2412
2416std::shared_ptr<FigureCanvas> FigureTool::BookATLASRectangular(const TString &figurename)
2417{
2418 return BookFigure(figurename, 800, 600);
2419}
2420
2423{
2424 for (auto &iter : BookedFigure)
2425 {
2426 MSGUser()->MSG_INFO("Draw ", iter.first.TString::Data());
2427 iter.second->Draw();
2428 iter.second->SaveAs(TString::Format("%s/%s", figuredir.TString::Data(), iter.first.TString::Data()));
2429 }
2430}
Figure class for TCanvas. A canvas is the base of your figure where you can define multiple NAGASH::F...
Definition FigureTool.h:490
std::shared_ptr< FigurePad > BookPad(const TString &padname, int lbx, int lby, int rtx, int rty, std::function< void(TPad *)> optionfunc=[](TPad *) {})
Book a FigurePad in this canvas.
FigureCanvas(std::shared_ptr< MSGTool > MSG, std::shared_ptr< FigureStyleHelper > shelper, const TString &elementname, int npx, int npy)
std::shared_ptr< FigurePad > BookPadNDC(const TString &padname, double lbx, double lby, double rtx, double rty, std::function< void(TPad *)> optionfunc=[](TPad *) {})
Book a FigurePad in this canvas. The position is given in relative coordinates.
virtual void CD() override
virtual void DrawElement() override
std::vector< FigureSquareRange > Range_vec
Definition FigureTool.h:108
std::shared_ptr< MSGTool > MSGUser()
Definition FigureTool.h:121
std::shared_ptr< MSGTool > msg
Definition FigureTool.h:115
virtual void SetStyle()
std::deque< std::shared_ptr< FigureElement > > LinkedElement
Definition FigureTool.h:110
std::shared_ptr< FigureElement > GetLinkElement(int index)
std::map< TString, uint64_t > MapLinkedElement
Definition FigureTool.h:111
std::shared_ptr< FigureStyleHelper > StyleUser()
Definition FigureTool.h:122
FigureElement * GetRootElement()
FigureElement * MotherElement
Definition FigureTool.h:112
FigureSquareRange Range_Total
Definition FigureTool.h:98
FigureElement(std::shared_ptr< MSGTool > MSG, std::shared_ptr< FigureStyleHelper > shelper, const TString &elementname, const TString &tyname, FigureElement *mother=0)
bool Contain(std::shared_ptr< FigureElement > subelement)
std::shared_ptr< FigureElement > FindLinkElement(const TString &name)
virtual void DrawElement()
bool IsType(const TString &tyname)
Definition FigureTool.h:125
int GetLinkIndex(const TString &name)
std::shared_ptr< FigureElement > TraceElement(const TString &name)
std::shared_ptr< FigureStyleHelper > stylehelper
Definition FigureTool.h:116
bool CheckDuplicate(const TString &name)
Figure class for TF1.
Definition FigureTool.h:250
std::function< void(TF1 *)> OptionFunc
Definition FigureTool.h:268
std::pair< double, double > GetMinAndMax(double, double)
virtual void DrawElement() override
FigureFunc1D(std::shared_ptr< MSGTool > MSG, std::shared_ptr< FigureStyleHelper > shelper, const TString &elementname, TF1 *func, const TString &option, FigureElement *mother, std::function< void(TF1 *)> optionfunc=[](TF1 *) {})
virtual void SetStyle() override
Figure class for TGraph.
Definition FigureTool.h:222
std::pair< double, double > GetMinAndMax(double, double)
std::function< void(TGraph *)> OptionFunc
Definition FigureTool.h:241
virtual void DrawElement() override
virtual void SetStyle() override
Figure class for THStack.
Definition FigureTool.h:180
FigureHStack(std::shared_ptr< MSGTool > MSG, std::shared_ptr< FigureStyleHelper > shelper, const TString &elementname, const std::vector< TString > &linkhists, const TString &option, FigureElement *mother)
void Scale(double)
Scale the histogram.
std::vector< TString > LinkedHists
Definition FigureTool.h:205
void DrawTotalHist(const TString &option, std::function< void(TH1D *)> optionfunc=[](TH1D *) {})
Whether draw the total hist of the hstack.
std::function< void(TH1D *)> total_hist_optionfunc
Definition FigureTool.h:214
virtual void DrawElement() override
TGraphErrors * total_hist_graph
Definition FigureTool.h:210
virtual void SetStyle() override
void Rebin(int)
Rebin the histogram.
std::pair< double, double > GetMinAndMax(double, double)
TString total_hist_drawoption
Definition FigureTool.h:213
Figure class for TH1D.
Definition FigureTool.h:132
std::pair< double, double > GetMinAndMax(double, double)
virtual void SetStyle() override
std::vector< TString > GetLinkObject()
FigureHist1D(std::shared_ptr< MSGTool > MSG, std::shared_ptr< FigureStyleHelper > shelper, const TString &elementname, TH1D *hist, const TString &option, FigureElement *mother, std::function< void(TH1D *)> optionfunc=[](TH1D *) {})
std::function< void(TH1D *)> OptionFunc
Definition FigureTool.h:162
std::function< void(TGraph *)> TGraphOptionFunc
Definition FigureTool.h:163
virtual void DrawElement() override
void Rebin(int)
Rebin the histogram.
TGraphErrors * mygraph
Definition FigureTool.h:160
void Scale(double)
Scale the histogram.
Figure class for TH2D.
Definition FigureTool.h:277
virtual void SetStyle() override
std::function< void(TH2D *)> OptionFunc
Definition FigureTool.h:296
virtual void DrawElement() override
FigureHist2D(std::shared_ptr< MSGTool > MSG, std::shared_ptr< FigureStyleHelper > shelper, const TString &elementname, TH2D *hist, const TString &option, FigureElement *mother, std::function< void(TH2D *)> optionfunc=[](TH2D *) {})
void Rebin(int, int)
Figure class for TLatex.
Definition FigureTool.h:305
std::function< void(TLatex *)> OptionFunc
Definition FigureTool.h:321
virtual void DrawElement() override
virtual void SetStyle() override
FigureLatex(std::shared_ptr< MSGTool > MSG, std::shared_ptr< FigureStyleHelper > shelper, const TString &content, double posx, double poxy, Color_t color, FigureElement *mother, std::function< void(TLatex *)> optionfunc=[](TLatex *) {})
Figure class for TPad. This is the class for drawing all the other elements(histograms,...
Definition FigureTool.h:329
TString GetXTitle()
Definition FigureTool.h:446
std::shared_ptr< FigurePad > BookPad(const TString &padname, int lbx, int lby, int rtx, int rty, std::function< void(TPad *)> optionfunc=[](TPad *) {})
Book a new pad in this pad.
void SetLogy(int value=1)
Set y-axis to be drawn in logarithmic scale.
std::shared_ptr< FigureGraph1D > SetInputGraph1D(const TString &elementname, TGraph *graph, const TString &option, std::function< void(TGraph *)> optionfunc=[](TGraph *) {})
Book a new FigureGraph1D on this pad.
TString legend_header
Definition FigureTool.h:433
void Norm(const TString &, const TString &, double xmin=0, double xmax=0)
Normalize one element to another.
std::function< void(TAxis *, TAxis *, TAxis *)> AxisOptionFunc
Definition FigureTool.h:402
void SetLegend(const TString &header="", const TString &option="")
Set the legend of this pad.
double GetZTitleOffset()
Definition FigureTool.h:451
virtual void DrawElement() override
void SetGridy(bool gridy=true)
Draw grids on y axis.
void SetGridx(bool gridx=true)
Draw grids on x axis.
std::shared_ptr< FigureHist1D > SetInputHist1DGraph(const TString &elementname, TH1D *hist, const TString &option, std::function< void(TGraph *)> optionfunc=[](TGraph *) {})
Book a FigureHist1D on this pad, the histogram will be converted to a TGraphErrors object when drawin...
bool user_set_legend_position
Definition FigureTool.h:435
std::shared_ptr< FigureHStack > SetHStack(const TString &elementname, const std::vector< TString > &linkinfo, const TString &option)
Book a new THStack on this pad, note that only one NAGASH::FigureHStack can be booked in a pad.
void SetXaxisRange(double min, double max)
Set the range of the x-axis to be drawn.
void SetLogz(int value=1)
Set z-axis to be drawn in logarithmic scale.
TString GetZTitle()
Definition FigureTool.h:448
FigurePad(std::shared_ptr< MSGTool > MSG, std::shared_ptr< FigureStyleHelper > shelper, const TString &elementname, int lbx, int lby, int rtx, int rty, FigureElement *mother, std::function< void(TPad *)> optionfunc=[](TPad *) {})
virtual void CD() override
void SetLogx(int value=1)
Set x-axis to be drawn in logarithmic scale.
void SetZaxisRange(double min, double max)
Set the range of the z-axis to be drawn.
std::shared_ptr< FigureHist2D > SetInputHist2D(const TString &elementname, TH2D *hist, const TString &option, std::function< void(TH2D *)> optionfunc=[](TH2D *) {})
Book a new FigureHist2D on this pad.
void SetLegendColumn(int)
Set the column number of the legend.
double GetXTitleOffset()
Definition FigureTool.h:449
std::vector< TString > legend_entries
Definition FigureTool.h:431
std::function< void(TPad *)> OptionFunc
Definition FigureTool.h:401
void SetLatex(const TString &content, double posx, double poxy, Color_t color=1, std::function< void(TLatex *)> optionfunc=[](TLatex *) {})
Book a new FigureLatex on this pad.
TString legend_header_option
Definition FigureTool.h:434
TString GetYTitle()
Definition FigureTool.h:447
double GetYTitleOffset()
Definition FigureTool.h:450
virtual void SetStyle() override
std::shared_ptr< FigureHist1D > SetInputHist1D(const TString &elementname, TH1D *hist, const TString &option, std::function< void(TH1D *)> optionfunc=[](TH1D *) {})
Book a FigureHist1D on this pad.
void SetLegendEntries(const std::vector< TString > &entries, const std::vector< TString > &options)
Set the entries passed to the legend, if this function is not called, all the elements in the pad wil...
void SetYaxisRange(double min, double max)
Set the range of the y-axis to be drawn.
std::vector< TString > legend_options
Definition FigureTool.h:432
std::shared_ptr< FigureFunc1D > SetInputFunc1D(const TString &elementname, TF1 *func, const TString &option, std::function< void(TF1 *)> optionfunc=[](TF1 *) {})
Book a new FigureFunc1D on this pad.
bool NeedBottomMargin()
Definition FigureTool.h:445
void DrawATLASLabel(const TString &content, double posx, double poxy, Color_t color=1, double space=-1)
Draw a "ATLAS" plus the given content like ATLAS Internal, the ATLAS text will be drawn slanted.
std::shared_ptr< MSGTool > MSGUser()
Definition FigureTool.h:73
virtual void SetPadStyle(FigurePad *pad)
virtual void SetLatexStyle(FigureLatex *latex)
virtual void SetFunc1DStyle(FigureFunc1D *func)
int DIVISION_N1
The number of primary divisions on the axis.
Definition FigureTool.h:59
double TITLE_MARGIN_PERCENT
The margin size for the title(left and bottom).
Definition FigureTool.h:48
virtual void SetHist1DGraphStyle(FigureHist1D *hist)
std::shared_ptr< MSGTool > msg
Definition FigureTool.h:68
virtual void SetGraph1DStyle(FigureGraph1D *graph)
double LEGEND_TEXT_SIZE_PERCENT
The size of the legend text as well as other text in the pad.
Definition FigureTool.h:55
virtual void SetHist2DStyle(FigureHist2D *hist)
double RIGHT_BLANK_MARGIN_PERCENT
The margin size on the right.
Definition FigureTool.h:51
double COLZ_MARGIN_PERCENT
The margin size for the z axis for 2D histogram COLZ draw option.
Definition FigureTool.h:49
FigureStyleHelper(std::shared_ptr< MSGTool > MSG)
virtual void SetHist1DStyle(FigureHist1D *hist)
double LeftPercentage
Control the left space to automatically place the legend.
Definition FigureTool.h:65
int DIVISION_N2
The number of secondary divisions on the axis.
Definition FigureTool.h:60
double TOP_BLANK_MARGIN_PERCENT
The margin size on the top.
Definition FigureTool.h:50
double TEXT_SIZE_PERCENT
The size of the text on the axis.
Definition FigureTool.h:54
double TICK_LENGTH_PERCENT
The length of the tick on the axis.
Definition FigureTool.h:53
int DIVISION_N3
The number of tertiary divisions on the axis.
Definition FigureTool.h:61
int TEXT_FONT
The font for the text.
Definition FigureTool.h:57
std::shared_ptr< FigureCanvas > BookFigure(const TString &figurename, int size_x, int size_y)
Book a new FigureCanvas as a new figure.
FigureTool(std::shared_ptr< MSGTool > MSG)
Constructor for FigureTool.
void DrawFigures()
Draw all the figures booked in this tool.
std::shared_ptr< FigureCanvas > BookATLASSquare(const TString &figurename)
Book a new FigureCanvas as a new figure. The size is 600*600 as recommended by ATLAS.
std::shared_ptr< FigureCanvas > BookATLASRectangular(const TString &figurename)
Book a new FigureCanvas as a new figure. The size is 800*600 as recommended by ATLAS.
std::map< TString, std::shared_ptr< FigureCanvas > > BookedFigure
Definition FigureTool.h:526
std::shared_ptr< FigureStyleHelper > stylehelper
Definition FigureTool.h:525
Provide interface for all tools in NAGASH.
Definition Tool.h:72
std::shared_ptr< MSGTool > MSGUser()
return the MSGTool inside.
Definition Tool.h:91