Draw multiple graphs

Hi,

I would like to draw in one Canvas many graphs (lets say 15), but I don’t want to type for every graph the command
TGraph *gr1 = …

The data for each graph are held by an array[i=15][j=200]. So I would like for each i to draw a graph in the same Canvas. Is there a way to name the pointer (gr) differently for each graph using a loop??

Thank you in advance.

Loukas

May be this example will help you:
$ROOTSYS/tutorials/graphs/multigraph.C

This is not what I meant.

I would like to have something like this:

for(i=1; i<=15; i++){
sprintf(graph,"gr%d",i);
for(int j =1; j<200; j++){
con[i] = totalNeutronsR[i][j];
}
TGraph *graph = new TGraph(200, tR, con);
graph->SetMarkerColor(1);
graph->SetMarkerSize(0.5);
graph->SetMarkerStyle(7);
}
TMultiGraph *mg = new TMultiGraph();
mg->Add(gr1);
mg->Add(gr2);
mg->Add(gr3);
mg->Add(gr4);
mg->Add(gr5);
mg->Add(gr6);
mg->Add(gr7);
mg->Add(gr8);
mg->Add(gr9);
mg->Add(gr10);
mg->Add(gr11);
mg->Add(gr12);
mg->Add(gr13);
mg->Add(gr14);
mg->Add(gr15);
mg->Draw("AP");

Well, the above code gives errors, but I was wondering if there is a way to have something like this ??

Thanks,
Loukas

you can do:

{
   TGraph *g[10];
   Double_t x[10] = {0,1,2,3,4,5,6,7,8,9};
   Double_t y[10] = {1,2,3,4,5,6,4,3,2,1};
   TMultiGraph *mg = new TMultiGraph();
   for (int i=0; i<10; i++) {
      g[i] = new TGraph(10, x, y);
      y[i] = y[i]+1;
      mg->Add(g[i]);
   }
   mg->Draw("AL");
}

Thanks for the tip.

I modified the code to fit into my needs but I still receive errors.
My code is:

TGraph *gr[25];
TMultiGraph *mg = new TMultiGraph();
for(int k=0; k<21; k++){
for(int l =1; l<200; l++){
concentration[l] = totalNeutronsR[k][l];
} //end of l loop
gr[k] = new TGraph(200, tR, concentration);
mg->Add(gr[k]);
} //end of k loop
mg->Draw("AP");

Any idea?

Thank you in advance,

Loukas

Can you send something running ? totalNeutronsR, and concentration are not declared in the code you sent.

I have declared them at the beginning…

It’s running !!!

I had just to quit ROOT and enter again…

Many thanks for your help!

regards,
Loukas

Hello! I have the same situation. In my program I have to analyse 1000 files and access a branch from the tree and execute some code. In the end I have to represent the results in a histogram wich have to contain the data from all the 1000 files. The problem is that the program overwrites the same canvas until the last one.

void read() {
   for (Int_t ii=1000; ii<=1005; ii++) {
      String fileName (Form ("2019_cl3_run%d_GroupMask_off26.root", ii)); 
      TFile treeFile(fileName.Data());

a part from the reading and

void paint ()
{
 hit.SetLineColor(kRed); 
  hit.Draw();
  hit. SetTitle("All ");
    hit.GetXaxis()->SetTitle("N");
    hit.GetYaxis()->SetTitle("Entries");
    hit.SetMarkerStyle(30);
    hit.SetMarkerColor(kRed+3);
  c1.Draw("hist");}"

Also, I created the canvas before the draw function , like ,

TCanvas c1("Param", "Nhit", 2800, 1000);
  TH1I hit("hit", "hit", 20, 0, 20);

Can you help me?

You should not Draw the canvas . But only the histogram hit. Like:

    hit.SetLineColor(kRed); 
    hit. SetTitle("All ");
    hit.GetXaxis()->SetTitle("N");
    hit.GetYaxis()->SetTitle("Entries");
    hit.SetMarkerStyle(30);
    hit.SetMarkerColor(kRed+3);
    hir.Draw("hist");

Also it seems that hit is drawn in the method Paint() but it looks declared elsewhere in your code. Is it global ?

When you draw hit with the option hist it will overwrite the previous plots. If you want to have several histograms drawing on the same plot you should use the option same or use a THStack which might be better if you have 1000 histograms in order to compute the global range.

Note: I have re-formatted your post. It was impossible to see relay the code.

Very late reply here, but I’m never sure about the general practice of using new. The tool my collaboration has an event display (we generate plots for each event in the detector and iterate to the next event with a GUI so we can take a peek at each event) so for each event we need to clear the graphics.

Am I going to have an issue if I have something like what’s above in a function that iterates over each event?


Asked as a decision between two options:

If I have a function that runs for each event, should I:

I have calls to new i and inside this event-by-event function and ROOT will call do the relevant calls to ~TGraph at the end of the scope of that call to new?

Or should I have an array that holds all the TGraph*'s (or even TGraph’s) then populate them and add them to the TMultiGraph and draw it, then clear them with TGraph::Set(0)?

Hi @orionyeung001,

thanks for asking! If you add the TGraphs to the TMultiGraph via TMultiGraph::Add(), you have to create them with new but don’t delete them because the TMultiGraph will now take care of that (as explained in the linked documentation).

Hope this helps!

Cheers,
Jonas

1 Like