using namespace std;
#include <iostream>
#include <iomanip>
#include <math.h>
//---- Root includes
#include <TCanvas.h>
#include <TColor.h>
#include <TDatime.h>
#include <TFile.h>
#include <TH2.h>
#include <TPaveText.h>
#include <TPostScript.h>
#include <TProfile.h>
#include <TROOT.h>
#include <TString.h>
#include <TStyle.h>
#include <TSystem.h>
//---- Hydra includes
#include "hades.h"
#include "hqaoutputps.h"
#include "hqascalers.h"
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-//
//*-- Author : Dan Magestro (magestro@gsi.de)
//*-- Modified : 24/01/2002
//*-- Modified : 24/10/2002 A.Sadovski (A.Sadovski@fz-rossendorf.de)
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-//
//_HADES_CLASS_DESCRIPTION
//////////////////////////////////////////////////////////////////////////////
//
// HQAOutputPS
//
// This class creates a postscript file using TPostScript, and histograms are
// added by iterating over TList(s) of active histograms.
// Histograms must be of type TH1F, TH2F, or TProfile.
//
// Scalers are added with a TList of HQAScaler and HQAScaler6 objects.
//
//
For more information, see the QA home page.
//
//////////////////////////////////////////////////////////////////////////////
ClassImp(HQAOutputPS)
HQAOutputPS::HQAOutputPS(TString fname) {
// Default constructor, filename must be supplied
fnamePS = fname;
fCanvas = 0;
fHistPad = 0;
histCount = 0;
pageCount = 0;
nEvent = 0; //Be carefull this is not an initialisation, in reality,
nProcessed = 0; //as "nEvent","nProcessed" assigned here using setStats function from hqaoutputps.h
nHistPerPage = 6;
kFIRST = kTRUE;
kPDF = kTRUE;
}
HQAOutputPS::~HQAOutputPS() {
// Default destructor
if(fCanvas) closePS();
if(kPDF) makePDF();
}
void HQAOutputPS::writeHist(TList *histList) {
// Output histograms to Root file (just a simple version)
TFile *ff = new TFile("ff.root","RECREATE");
ff->cd();
TIter next(histList);
while (TH1 *h = (TH1*) next()) {
if( !strcmp(h->ClassName(),"TH1F") )
((TH1F*)h)->Write();
else if( !strcmp(h->ClassName(),"TH2F") )
((TH2F*)h)->Write();
else if( !strcmp(h->ClassName(),"TProfile") )
((TProfile*)h)->Write();
}
cout << "-----------------------------------------" << endl;
cout << "| Before the closing the file ff.root |" << endl;
cout << "-----------------------------------------" << endl;
ff->Close();
}
void HQAOutputPS::writeHist(TList *histList1, TList *histList2, TString fnamePS) {
// Output histograms to Root file (not really implemented yet)
// modified for 2 TLists to be plotted at ones
TString histDirName;
TDirectory *histDir=NULL;
TString histFile = fnamePS(0,fnamePS.Last('.'))+"_hist.root";
//FILE* fSC = fopen( histFile, "w");
//TFile *ff = new TFile("ff.root","RECREATE");
TFile *ff = new TFile( histFile,"RECREATE");
ff->cd();
{
TIter next(histList1);
while (TH1 *h = (TH1*) next()) {
// go to the appropriate directory, create new if does not exist
TString opt = next.GetOption();
opt.ToLower();
if(opt.Index("--")>0){
histDirName = opt(0,opt.Index("--"));
histDir = (TDirectory *)ff->FindObject(histDirName);
if( histDir && !( strcmp (histDir->ClassName(), "TDirectory"))){
ff->cd(histDirName);
}else{ // try to create new directory
if( (ff->mkdir(histDirName) )){
ff->cd(histDirName);
}else{
histDirName = "";
ff->cd();
}
}
}
if( !strcmp(h->ClassName(),"TH1F") )
((TH1F*)h)->Write();
else if( !strcmp(h->ClassName(),"TH2F") )
((TH2F*)h)->Write();
else if( !strcmp(h->ClassName(),"TProfile") )
((TProfile*)h)->Write();
}
}
ff->cd();
{
TIter next(histList2);
while (TH1 *h = (TH1*) next()) {
// go to the appropriate directory, create new if does not exist
TString opt = next.GetOption();
opt.ToLower();
if(opt.Index("--")>0){
histDirName = opt(0,opt.Index("--"));
histDir = (TDirectory *)ff->FindObject(histDirName);
if( histDir && !( strcmp (histDir->ClassName(), "TDirectory"))){
ff->cd(histDirName);
}else{ // try to create new directory
if( (ff->mkdir(histDirName) )){
ff->cd(histDirName);
}else{
histDirName = "";
ff->cd();
}
}
}
if( !strcmp(h->ClassName(),"TH1F") )
((TH1F*)h)->Write();
else if( !strcmp(h->ClassName(),"TH2F") )
((TH2F*)h)->Write();
else if( !strcmp(h->ClassName(),"TProfile") )
((TProfile*)h)->Write();
}
}
ff->Close();
}
void HQAOutputPS::makeHist(TList *histList) {
// This is the class's main function. The canvas is defined, and the TList of
// histograms is iterated. Each histogram is drawn according to its type.
TString type,typeKeep;
// Open file if this is the first call to make()
if(kFIRST) {
setStyle();
TVirtualPS *temp=0;
// This code is ugly, but it gets around a TPad/TPostScript problem and I'm
// working on fixing it (D.Magestro 18/2/02)
if(gVirtualPS) {
temp = gVirtualPS;
gVirtualPS = 0;
}
fCanvas = new TCanvas("canvas","HADES diagnostics",200,320);
if(!gVirtualPS) {
gVirtualPS = temp;
}
Open(fnamePS,111);
}
setStyle();
// QA histograms
TIter next(histList);
while (TH1 *h = (TH1*) next()) {
TString opt = next.GetOption();
opt.ToLower();
if(opt.Contains("notshown")) continue; // If you want to have histogram in root file but not in
// pdf file use option "notshown"
//////////////////////////////////////////////////////////////////////
//cheeck one step forward if it is not an overlayed histogramm will be
//
//Basically it is done to prevent situation when
//we plot severall histograms on top of the firtst one
//which may happen to be empty, then all the following
//by "same" mode will simply owerflow up, and information
//will be lost.
//So, we analyse instead for each normal historgam if there are
//any number of same behind it, and if so we compare h->GetMaximum
//for the "first" one and all the subsequent "same" ones and
//assign for the "first" histogram maximal y-axis range, and
//this prevents the overflow...
//
TIter nex2(histList);
while (TH1 *h2 = (TH1*) nex2()) {
if(h2==h){
if(TH1 *h2 = (TH1*) nex2()){
TString opt2 = nex2.GetOption();
opt2.ToLower();
if(opt2.Contains("same")){
Double_t m1 = h->GetMaximum();
Double_t m2 = h2->GetMaximum();
//cout <<"m1,m2" <<m1<<m2<<endl;
if(m1>m2){
}else{
m1=m2;
}
h->SetMaximum(m1*1.2);
//cout << "m1="<<m1<<endl;
Int_t iSame = 1; //first time we should try anyway (we do not know that is the next option, may be it is "same" again)
while(iSame){
//One more time for the next "same" if so... (previous "same" is meant by if see upstream^)
if(TH1 *h2 = (TH1*) nex2()){
TString opt2 = nex2.GetOption();
opt2.ToLower();
if(opt2.Contains("same")){
m2 = h2->GetMaximum();
//cout <<"m1,m2" <<m1<<m2<<endl;
if(m1>m2){
}else{
m1=m2;
}
h->SetMaximum(m1*1.2);
//cout << "m1="<<m1<<endl;
}else{
//indicate that we shoud drop this "same" procedure
iSame = 0;
}
}
}
}
}
}
}
//////////////////////////////////////////////////////////////////////
if( opt.Contains("same") ){
//do not ask for a new panel
}else{
//ask for a new panel
histCount++;
}
if(opt.Index("--")>0) {
type = opt(0,opt.Index("--"));
if( (type.CompareTo(typeKeep)) ) {
if(!kFIRST) fCanvas->Update();
histCount = 1;
pageCount = 0;
makeNewPage(type);
typeKeep = type;
}
}
if(histCount > nHistPerPage || opt.Contains("newpage")) {
//cout<<"--nb of hist: "<<histCount<<" maxPerPage: "<<nHistPerPage<<" det Type: "<<type<<endl;
fCanvas->Update();
makeNewPage(type);
histCount = 1;
}
fHistPad->cd(histCount);
// Adjust left,right margins for (1,3) division
if(fHistPad->GetListOfPrimitives()->GetSize()==3) {
gPad->SetLeftMargin(0.15);
gPad->SetRightMargin(0.05);
}
// Set log scale, if histogram isn't empty and option is set
if( h->GetEntries() ) {
if( opt.Contains("logx") ) gPad->SetLogx(1);
if( opt.Contains("logy") ) gPad->SetLogy(1);
if( opt.Contains("logz") ) gPad->SetLogz(1);
}
// Set grid X,Y
if( opt.Contains("gridx") ) gPad->SetGridx();
if( opt.Contains("gridy") ) gPad->SetGridy();
h->SetLineWidth(2);
// Format histograms
if( opt.Contains("same") ){
//do not assign any color, it must be specified in the histogramm definition
}else{
if( !strcmp(h->ClassName(),"TProfile") )
h->SetLineColor(1);
else if( !strcmp(h->ClassName(),"TH1F") )
h->SetLineColor(4);
}
// Format axis titles
h->GetXaxis()->CenterTitle();
h->GetYaxis()->CenterTitle();
h->SetTitleOffset(1.1,"X");
h->SetTitleOffset(1.1,"Y");
h->SetTitleSize(.05,"X");
h->SetTitleSize(.05,"Y");
h->SetNdivisions(208,"X");
h->SetNdivisions(208,"Y");
// Set axis ranges so that variation histogram is full and looks nice
if( opt.Contains("var") ) {
Int_t binMax = h->FindBin(nEvent);
TProfile *prof = (TProfile*) h;
if(binMax < 200) {
Float_t xMax = h->GetBinCenter( binMax+1 );
h->SetAxisRange(0,xMax);
}
Float_t min=10000,max=0;
Float_t cont=0,err=0;
for(Int_t i=1;i<=binMax;i++) {
cont=prof->GetBinContent(i);
err=prof->GetBinError(i);
if((cont+err)>max) max=cont+err;
if((cont-err)<min) min=cont-err;
}
prof->SetMaximum(max + (max-min));
prof->SetMinimum(min - (max-min));
if((min-(max-min))<0) prof->SetMinimum(0);
}
// Set options depending on histogram type
if( !strcmp(h->ClassName(),"TH2F") ) h->SetOption("colz");
if( opt.Contains("lego2") )h->SetOption("lego2");
// Overlay options are quiet usefull.
//if( opt.Contains("same") ) h->SetOption("same");
// Draw histograms
if( opt.Contains("same") ){
h->DrawCopy("same");
}else{
h->DrawCopy();
}
/////
// Add some color text markers for
// 6-th sectored histograms: this part is responsible for the color rose
// in case of 6-th sectors interlayed histograms
/////
if( opt.Contains("6sec")){
#include "QAsectioncolors.h"
Float_t x0 = 0.76;
Float_t y0 = 0.76;
Float_t a = 0.06;
TText s6txt[6];
for(Int_t i=0; i<6; i++){
s6txt[i].SetTextSize(0.06);
s6txt[i].SetTextColor(SectColor[i]);
}
s6txt[0].DrawTextNDC( x0 , y0+a , "s1"); //s1
s6txt[1].DrawTextNDC( x0+0.87*a, y0+a*0.5 , "s2"); //s2
s6txt[2].DrawTextNDC( x0+0.87*a, y0-a*0.5 , "s3"); //s3
s6txt[3].DrawTextNDC( x0 , y0-a , "s4"); //s4
s6txt[4].DrawTextNDC( x0-0.87*a, y0-a*0.5 , "s5"); //s5
s6txt[5].DrawTextNDC( x0-0.87*a, y0+a*0.5 , "s6"); //s6
}
if( opt.Contains("3mod")){
#include "QAsectioncolors.h"
Float_t x0 = 0.7;
Float_t y0 = 0.76;
Float_t a = 0.06;
TText s3txt[3];
for(Int_t i=0; i<3; i++){
s3txt[i].SetTextSize(0.06);
s3txt[i].SetTextColor(ModColor[i]);
}
s3txt[0].DrawTextNDC( x0 , y0+a , "Pre"); //s1
s3txt[1].DrawTextNDC( x0, y0 , "Post1"); //s2
s3txt[2].DrawTextNDC( x0, y0-a , "Post2"); //s3
}
// Draw the mean on the profile histogram plots as a horiz. line
if( !strcmp(h->ClassName(),"TProfile") ) {
TProfile *prof = (TProfile*) h->Rebin(200,"prof");
Float_t mean = prof->GetBinContent(1);
TLine *l = new TLine(0.,mean,nEvent,mean);
l->SetLineWidth(2);
l->SetLineColor(4);
l->Draw();
}
if(kFIRST) kFIRST=kFALSE;
}
}
void HQAOutputPS::makeText(TList *scalerList) {
// Method for generating output for scalers
TString type,typeKeep;
Char_t out[200];
if(fCanvas) fCanvas->Update();
// Open file if this is the first call to make()
if(kFIRST) {
setStyle();
fCanvas = new TCanvas("canvas","HADES diagnostics",200,320);
Open(fnamePS,111);
}
pageCount = 0;
nHistPerPage = 1;
makeNewPage("Scalers");
fHistPad->cd(1);
//---- Sectorwise scalers
Int_t nLines = 0;
TIter next(scalerList);
next.Reset();
TNamed *t=0;
while ((t = (TNamed*) next.Next())) {
TString opt = next.GetOption();
opt.ToLower();
if(opt.Contains("sectorwise")) {
nLines++;
if(opt.Index("--")>0) {
type = opt(0,opt.Index("--"));
if( (type.CompareTo(typeKeep)) ) { // Add line between detector types
typeKeep = type;
nLines++;
}
}
}
}
typeKeep = "";
// Define text box
TPaveText *pt = new TPaveText(0.01,0.98-0.02*nLines,0.96,0.98,"b1NDC");
pt->SetBorderSize(0);
pt->SetFillColor(10);
pt->SetTextAlign(13);
pt->SetTextSize(0.018);
pt->SetMargin(0.01);
pt->SetTextFont(102);
next.Reset();
while (TNamed *h = (TNamed*) next()) {
TString opt = next.GetOption();
opt.ToLower();
if( opt.Contains("sectorwise") ) {
HQAScaler6 &scal = *((HQAScaler6*) h);
if(opt.Index("--")>0) {
type = opt(0,opt.Index("--"));
if( (type.CompareTo(typeKeep)) ) {
sprintf(out," Sec.0 Sec.1 Sec.2 Sec.3 Sec.4 Sec.5");
nLines++;
TText *t = pt->AddText(out);
t->SetTextColor(4);
typeKeep = type;
}
}
sprintf(out,"%40s %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f",
scal.GetTitle(),scal[0],scal[1],scal[2],scal[3],scal[4],scal[5]);
pt->AddText(out);
}
if(kFIRST) kFIRST=kFALSE;
}
pt->Draw();
}
void HQAOutputPS::saveScal(TList *scalerList, TString fnamePS) {
// Derived from //Method for generating output for scalers
// Used to save scalers into txt-file
TString type,typeKeep;
//Char_t out[200];
TString txtFile = fnamePS(0,fnamePS.Last('.'))+".txt";
FILE* fSC = fopen( txtFile, "w");
//---- Sectorwise scalers
Int_t nLines = 0;
TIter next(scalerList);
next.Reset();
TNamed *t =0;
while ( (t = (TNamed*) next.Next())) {
TString opt = next.GetOption();
opt.ToLower();
if(opt.Contains("sectorwise")) {
nLines++;
if(opt.Index("--")>0) {
type = opt(0,opt.Index("--"));
if( (type.CompareTo(typeKeep)) ) { // Add line between detector types
typeKeep = type;
nLines++;
}
}
}
}
typeKeep = "";
//cout << " Sec.0 Sec.1 Sec.2 Sec.3 Sec.4 Sec.5" << endl;
fprintf(fSC,"%s"," Sec.0 Sec.1 Sec.2 Sec.3 Sec.4 Sec.5n");
next.Reset();
while (TNamed *h = (TNamed*) next()) {
TString opt = next.GetOption();
opt.ToLower();
if( opt.Contains("sectorwise") ) {
HQAScaler6 &scal = *((HQAScaler6*) h);
//sprintf(out,"%40s %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f",
// scal.GetTitle(),scal[0],scal[1],scal[2],scal[3],scal[4],scal[5]);
//cout << out << endl;
fprintf(fSC,"%40s %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f n",
scal.GetTitle(),scal[0],scal[1],scal[2],scal[3],scal[4],scal[5]);
}
}
fclose( fSC );
}
void HQAOutputPS::closePS() {
// Closes files and deletes the canvas
fCanvas->Update();
Close();
delete fCanvas;
}
void HQAOutputPS::makePDF() {
// Execute ps2pdf GhostScript command on closed PS file, delete PS file
TString fnamePDF = fnamePS(0,fnamePS.Last('.'))+".pdf";
TString command = "ps2pdf " + fnamePS + " " + fnamePDF;
gSystem->Exec(command);
command = "if [ -e " + fnamePDF + " ]; then rm " + fnamePS + "; else echo -e "==> PDF file " + fnamePDF + " does not exist"; fi;";
gSystem->Exec(command);
}
void HQAOutputPS::makeNewPage(TString type) {
// In addition to making a new page in the PS file, this function writes the
// header at the top of each page and defines the histogram pad.
Char_t pageTitle[120],fileTitle[120],dateTitle[120],eventTitle[120],procTitle[120];
NewPage();
pageCount++;
fCanvas->Clear();
type.ToUpper();
if(fnameDST.Contains("/"))
fnameDST = fnameDST( fnameDST.Last('/')+1,fnameDST.Length() );
if(type.Contains("SCALER") && !type.Contains("DAQ") ) sprintf(pageTitle,"Scalers (page %i)",pageCount);
else sprintf(pageTitle,"%s histograms (page %i)",type.Data(),pageCount);
//cout<<"---page type= "<<type<<endl;
//cout<<"----PageTitle= "<<pageTitle<<endl;
sprintf(fileTitle,"%s%s","DST file = ",fnameDST.Data());
sprintf(eventTitle,"%s%i","Number of events in file= ",(int)nEvent);
sprintf(procTitle,"Number of QA'd events = %i (%.0f%% sampled)", nProcessed,
(float) nProcessed/nEvent*100. );
Char_t dt[25];
TDatime tt;
strcpy(dt,tt.AsString());
sprintf(dateTitle,"%s%s","This page generated ",dt);
TPaveText *pt = new TPaveText(0.01,0.975,0.99,0.999,"blNDC");
pt->SetBorderSize(0);
pt->SetFillColor(10);
pt->AddText("HADES QA Report");
pt->Draw();
TPaveText *pt1 = new TPaveText(0.01,0.926,0.49,0.975,"blNDC");
pt1->SetBorderSize(0);
pt1->SetFillColor(10);
pt1->SetTextAlign(13);
pt1->SetTextSize(.02);
pt1->AddText(fileTitle);
pt1->AddText(eventTitle);
pt1->AddText(procTitle);
pt1->Draw();
TPaveText *pt2 = new TPaveText(0.51,0.926,0.99,0.975,"blNDC");
pt2->SetBorderSize(0);
pt2->SetFillColor(10);
pt2->SetTextAlign(13);
pt2->SetTextSize(.02);
pt2->AddText(dateTitle);
TText *text = pt2->AddText(pageTitle);
text->SetTextSize(.025);
pt2->Draw();
// Divide remaining area of canvas into sub-pads
fHistPad = new TPad("histPad","Histogram pad",.001,.001,.999,.925);
if(nHistPerPage == 1) fHistPad->Divide(1,1);
if(nHistPerPage == 3) fHistPad->Divide(1,3);
if(nHistPerPage == 4) fHistPad->Divide(2,2);
if(nHistPerPage == 6) fHistPad->Divide(2,3);
if(nHistPerPage == 8) fHistPad->Divide(2,4);
fHistPad->Draw();
}
void HQAOutputPS::setStyle() {
// Set drawing styles for histograms and PostScript file
gStyle->SetOptStat(0);
TColor *col = gROOT->GetColor(51);
if (col) col->SetRGB(.636666,.35,.85);
// Optimized "pretty palette" to distribute colors better
//Int_t colorArray[30] = {10,19,18,17,16,
// 51,52,54,57,60,
// 62,64,66,67,68,
// 70,72,74,80,86,
// 88,89,90,91,92,
// 93,94,96,98,100};
//gStyle->SetPalette(30,colorArray);
gStyle->SetPalette(1);
// Histogram title formatting
gStyle->SetTitleTextColor(4);
gStyle->SetTitleColor(10);
gStyle->SetTitleBorderSize(0);
// gStyle->SetTitleX(.2);
// gStyle->SetTitleY(.97);
gStyle->SetTitleH(.065);
gStyle->SetTitleW(1);
gStyle->SetHistMinimumZero();
// Canvas and pad formatting
gStyle->SetPadColor(10);
gStyle->SetPadBorderMode(0);
gStyle->SetCanvasColor(10);
gStyle->SetCanvasBorderMode(0);
gStyle->SetPadLeftMargin(0.10);
gStyle->SetPadTopMargin(0.10);
gStyle->SetPaperSize(20.,27.);
}
ROOT page - Class index - Class Hierarchy - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.