Multiple Questions about histograms and relating objects

Hi,

I have a few questions about drawing a histogram from a script/function and customizing the histogram. I’ve written a script which I compiled, so that it provides a funktion with wich I can draw all the histograms I want from a given tree. Now first the real questions:

  1. How do I add a label to a tick of a colorpalette, because I sometimes want to draw a 2D histogram with colz, where the z-range is from 1 to less than 10. Now the way root labels the palette, there is only a label for the 1 and no other labels. So how can I add a label for the maximum value that is on the palette? I’ve seen that the palette has a TGAxis instead of a TAxis, so I can’t use the normal SetBinLabel.

  2. Is there any way to paint directly to a .ps file instead of painting to a new window every time?

Now some questions that are more of an interest basis:
3. When I’m trying to access the statistics of a histogram, I can only get them from the ListOfFunctions, when the histogram was already drawn. Is that right, or is there any way to avoid having to draw a histogram, then move the statistics (so they are not blocking the colorpalette) and then draw it again?

  1. When I first fill a histogram, then write to a file, I get a segmentation violation when I try to draw it afterwards, is that some kind of feature of the Write function, or am I doing something else wrong?

  2. When I’m changing the right margin of a pad in which I’m drawing a histogram, which was read from a file, in order to be able to see which power of ten the colors are, the histogram gets a greater margin to the right edge of the pad, but the color palette stays close to the edge where it was before. But when I create the histogram, fill it, and then draw it into said pad, everything is fine. Why?

If someone could address any of the questions I would be very grateful.

  1. do you have an example showing the problem ?

  2. start in batch mode and do canvas->Print(" a.ps")

    1. and 5. can you send examples ?

Okay, the code is:
draw_test.cc:
#include “TFile.h”
#include “TTree.h”
#include “TObjArray.h”
#include “TChain.h”
#include “TH1F.h”
#include “TH2F.h”
#include “TCanvas.h”
#include “TPad.h”
#include “TVirtualPad.h”
#include “TPaveStats.h”
#include “TList.h”
#include “TPaletteAxis.h”
#include “TSpectrum.h”
#include “TVirtualFitter.h”
#include “TF1.h”

#include <string.h>
#include <stdio.h>
#include
#include

#include “draw_test.hh”

using namespace std;

void set_statistics_test(TH1F* hist, Double_t x1ndc, Double_t y2ndc)
{
TPaveStats* st;
Double_t xwidth;
Double_t ywidth;
st = (TPaveStats*)hist->GetListOfFunctions()->FindObject(“stats”);
if(st != 0)
{
xwidth = st->GetX1NDC() - st->GetX2NDC();
ywidth = st->GetY2NDC() - st->GetY1NDC();
st->SetX1NDC(x1ndc);
st->SetX2NDC(x1ndc-xwidth);
st->SetY1NDC(y2ndc-ywidth);
st->SetY2NDC(y2ndc);
}
else
{
cout<<“ERROR, “<GetName()<<”: stats not found”<<endl;
}
return;
}

void set_statistics_test(TH2F* hist, Double_t x1ndc, Double_t y2ndc)
{
TPaveStats* st;
Double_t xwidth;
Double_t ywidth;
st = (TPaveStats*)hist->GetListOfFunctions()->FindObject(“stats”);
if(st != 0)
{
xwidth = st->GetX1NDC() - st->GetX2NDC();
ywidth = st->GetY2NDC() - st->GetY1NDC();
st->SetX1NDC(x1ndc);
st->SetX2NDC(x1ndc-xwidth);
st->SetY1NDC(y2ndc-ywidth);
st->SetY2NDC(y2ndc);
}
else
{
cout<<“ERROR, “<GetName()<<”: stats not found”<<endl;
}
Double_t max = hist->GetMaximum();
hist->SetAxisRange(1,max,“Z”);
if(max < 10)
{
TPaletteAxis* pal;
pal = (TPaletteAxis*)hist->GetListOfFunctions()->FindObject(“palette”);
if(pal != 0)
{
//pal->GetAxis()->SetLabelSize(0.03);
//Int_t tmp = pal->GetAxis()->FindBin(max);
//pal->GetAxis()->SetBinLabel(tmp, max);
}
}
return;
}

void transfer_draw_test(char* name, int make_hists = 1, int make_ps = 1, double Eex_min = -30, double Eex_max = 5)
{
if(make_hists == 0 && make_ps == 0)
{
cout<<“Don’t make hists AND don’t make ps? Done!”<<endl;
return;
}

char tmpname[100];
TFile* infile = NULL;
TFile* outfile = NULL;
TTree* tree;
//histograms
//no cut
TH1F* hEex;

if(make_hists == 1)
{
strcpy(tmpname, name);
strcat(tmpname, “.root”);

  cout<<"opening file "<<tmpname<<" for reading ..."<<endl;
  infile = new TFile(tmpname, "read");
  if(infile->IsZombie())
{
  return;
}
  
  strcpy(tmpname, name);
  strcat(tmpname, "_hists.root");
  
  cout<<"opening file "<<tmpname<<" for writing ..."<<endl;
  outfile = new TFile(tmpname, "recreate");
  if(outfile->IsZombie())
{
  return;
}

  tree = (TTree*) infile->Get("grt");
  
  if(!tree)
{
  cout << "could not find tree grt in file " << tmpname << endl;
  return;
}
  
  //Declaration of leaves
  SiEvtData* se;
  RealData* r;
  
  //Set branch addresses
  tree->SetBranchAddress("SiEvtData",&se);
  tree->SetBranchAddress("RealData",&r);
  
  //histograms
  //no cut
  hEex = new TH1F("hEex","hEex;excitation energy in MeV;counts", 1000, Eex_min, Eex_max);

  Double_t nentries = tree->GetEntries();
  Int_t nbytes = 0;

  for (Int_t i=0; i<nentries;i++) 
{
  nbytes += tree->GetEvent(i);

  for(Int_t evt=0; evt<8; evt++)
    {
      hEex->Fill(se->Eex[evt]);
    }
  if(i%1000 == 0)
    cout<<((Int_t)(100.*i/nentries))<<" % done\r"<<flush;
}
  
  if(make_ps == 0)
{
  //write histograms
  hEex->Write();
  
  outfile->Close();
}
}

else if(make_hists == 0)
{
strcpy(tmpname, name);
strcat(tmpname, “_hists.root”);

  cout<<"opening file "<<tmpname<<" ... "<<flush;
  infile = new TFile(tmpname, "read");
  cout<<"done"<<endl;
  if(infile->IsZombie())
{
  return;
}
  //read histograms
  hEex = (TH1F*) infile->Get("hEex");
}

else
{
cout<<“only make_hists = 0,1 are defined!”<<endl;
return;
}

if(make_ps == 1)
{
//set statistics position
Double_t x1left = 0.1;
Double_t y2high = 0.9;
Double_t x1right = 0.69;
Double_t y2low = 0.55;

  set_statistics_test(hEex, x1left, y2high);

  //canvases: hEex, hEex_cm, hCD, hdE_E; nocut, cmul = 0,1,2, 171, 171bg, coinc, nocoinc
  char* tmpdir;
  int pos;
  char dir[100];
  tmpdir = strrchr(name,'/');

  TCanvas* canvas1;
  if(tmpdir != 0)
{
  pos = tmpdir-name+1;
  if(pos < 100)
    {
      strncpy(dir,name,pos);
    }
  strcpy(tmpname, tmpdir+1);
  canvas1 = new TCanvas(name,name,400,600);
  strcpy(tmpname, dir);
  strcat(tmpname, "htest_");
  strcat(tmpname, tmpdir+1);
}
  else
{
  canvas1 = new TCanvas(name,name,400,600);
  strcpy(tmpname, "htest_");
  strcat(tmpname, name);
}
  strcat(tmpname, ".ps");

  canvas1->Divide(1,2,0,0);

  TVirtualPad* subpad1;

  subpad1 = canvas1->cd(1);
  subpad1->SetBorderMode(0);
  subpad1->SetBorderSize(0);
  subpad1->SetLogy(1);
  hEex->Draw();

  canvas1->Print(tmpname);

  if(make_hists == 1)
{
  cout<<"start writing to file ... "<<flush;
  //write histograms
  hEex->Write();
  cout<<"done"<<endl;	  

  outfile->Close();
}
}

return;
}

draw_test.hh just contains class definitions for the tree.

see first attachment

okay, I know how to print a canvas, but can I draw a histogram to a canvas, without getting a new window with the canvas? I just want to call the funtion from the code above, without getting all the canvases drawn.

When I call the function transfer_draw_test(“filename”) I get as output:
opening file /nfs/d40/cb/vbildste/data/jul_03_mg30_SP_170305.root for reading …
opening file /nfs/d40/cb/vbildste/data/jul_03_mg30_SP_170305_hists.root for writing …
ERROR, hEex: stats not found
Info in TCanvas::Print: ps file /nfs/d40/cb/vbildste/data/htest_jul_03_mg30_SP_170305.ps has been created
start writing to file … done

When I then call transfer_draw_test(“filename”,0), which simply reads the already created file, I get no error:
opening file /nfs/d40/cb/vbildste/data/jul_03_mg30_SP_170305_hists.root … done
Info in TCanvas::Print: ps file /nfs/d40/cb/vbildste/data/htest_jul_03_mg30_SP_170305.ps has been created

just put the ->Write(); statement into the if(make_hists == 1) condition without checking whether ps-files should be created afterwards, that gives:

opening file /nfs/d40/cb/vbildste/data/jul_03_mg30_SP_170305.root for reading …
opening file /nfs/d40/cb/vbildste/data/jul_03_mg30_SP_170305_hists.root for writing …
99 % done
*** Break *** segmentation violation

Generating stack trace…
0x0000002a9ac6f1ab in set_statistics_test(TH1F*, double, double) + 0x3b from /nfs/us0/cb/vbildste/./draw_test_cc.so
0x0000002a9ac6f594 in transfer_draw_test(char*, int, int, double, double) + 0x1b4 from /nfs/us0/cb/vbildste/./draw_test_cc.so
0x0000002a9ac6fc70 in from /nfs/us0/cb/vbildste/./draw_test_cc.so
0x0000002a95facd43 in G__call_cppfunc + 0x1e3 from /cern/root_v4.01.02/x86_64///lib/root/libCint.so
0x0000002a95f8c412 in G__interpret_func + 0x1762 from /cern/root_v4.01.02/x86_64///lib/root/libCint.so
0x0000002a95f72bec in G__getfunction + 0x188c from /cern/root_v4.01.02/x86_64///lib/root/libCint.so
0x0000002a95f545cc in G__getitem + 0x13c from /cern/root_v4.01.02/x86_64///lib/root/libCint.so
0x0000002a95f557c8 in G__getexpr + 0x2c8 from /cern/root_v4.01.02/x86_64///lib/root/libCint.so
0x0000002a95fb774a in G__exec_function + 0x17a from /cern/root_v4.01.02/x86_64///lib/root/libCint.so
0x0000002a95fba810 in G__exec_statement + 0x29e0 from /cern/root_v4.01.02/x86_64///lib/root/libCint.so
0x0000002a95f44b40 in G__exec_tempfile_core + 0x2a0 from /cern/root_v4.01.02/x86_64///lib/root/libCint.so
0x0000002a95f44dc0 in G__exec_tempfile_fp + 0x10 from /cern/root_v4.01.02/x86_64///lib/root/libCint.so
0x0000002a95fc377f in G__process_cmd + 0x344f from /cern/root_v4.01.02/x86_64///lib/root/libCint.so
0x0000002a95876069 in TCint::ProcessLine(char const*, TInterpreter::EErrorCode*) + 0x159 from /cern/root_v4.01.02/x86_64///lib/root/libCore.so
0x0000002a957d8840 in TApplication::ProcessLine(char const*, bool, int*) + 0x540 from /cern/root_v4.01.02/x86_64///lib/root/libCore.so
0x0000002a9723a4aa in TRint::HandleTermInput() + 0x1ba from /cern/root_v4.01.02/x86_64///lib/root/libRint.so
0x0000002a9723a167 in TTermInputHandler::Notify() + 0x17 from /cern/root_v4.01.02/x86_64///lib/root/libRint.so
0x0000002a9723b9dd in TTermInputHandler::ReadNotify() + 0xd from /cern/root_v4.01.02/x86_64///lib/root/libRint.so
0x0000002a95913cdb in TUnixSystem::CheckDescriptors() + 0x15b from /cern/root_v4.01.02/x86_64///lib/root/libCore.so
0x0000002a959145be in TUnixSystem::DispatchOneEvent(bool) + 0x5ee from /cern/root_v4.01.02/x86_64///lib/root/libCore.so
0x0000002a9583aac5 in TSystem::InnerLoop() + 0x15 from /cern/root_v4.01.02/x86_64///lib/root/libCore.so
0x0000002a9584402d in TSystem::Run() + 0x8d from /cern/root_v4.01.02/x86_64///lib/root/libCore.so
0x0000002a957d71df in TApplication::Run(bool) + 0x1f from /cern/root_v4.01.02/x86_64///lib/root/libCore.so
0x0000002a9723acd6 in TRint::Run(bool) + 0x316 from /cern/root_v4.01.02/x86_64///lib/root/libRint.so
0x00000000004011bd in main + 0x4d from /cern/root_v4.01.02/x86_64///bin/root.exe
0x0000002a979dae5d in __libc_start_main + 0xfd from /lib64/tls/libc.so.6
0x00000000004010ca in TApplicationImp::ShowMembers(TMemberInspector&, char*) + 0x3a from /cern/root_v4.01.02/x86_64///bin/root.exe

see 2. attachment, first the histograms were filled and drawn with SetRightMargin(.15), then the file was loaded and the histograms drawn with SetRightMargin(0) (above function with make_hists = 0).
h_eloss_jul_03_mg30_SP_170305.ps (70.3 KB)
hCD_t_jul_03_mg30_SP_170305.ps (238 KB)

here is an example generating a PS file without a pad providing you start root with option “-b”

{
  c1 = new TCanvas("c1");
  TPostScript ps1("ps1.ps",111);
  hpxpy  = new TH2F("hpxpy","py vs px",40,-4,4,40,-4,4);                
  Float_t px, py, pz;
  for (Int_t i = 0; i < 25000; i++) {
     gRandom->Rannor(px,py);
     pz = px*px + py*py;
     Float_t random = gRandom->Rndm(1);
     hpxpy->Fill(px,py);            
  }
  hpxpy->Draw("colz");
  ps1.Close();
}

I see your labeling problem on th PS file (I guess). You do not have enough labels in log scale on the palette. You can add more log labels with the following comands:

  hpxpy->Draw("colz");
  c1->Update();
  TPaletteAxis *palette = (TPaletteAxis*)hpxpy->GetListOfFunctions()->FindObjec>
  palette->GetAxis()->SetMoreLogLabels();