Plotting multiple 1D profile histograms (TProfile) on one canvas


I have three separate 1D profile plots that I want to plot on one canvas, I defined three separate TProfile objects all have empty titles with the same number of bins and the same ranges for x and for y. I also put “SAME” as arguments in the Draw() function for the second and third profile plot. But for some reason, the plot result only shows the first profile plot. The other two plots are definitely being filled as I’m able to extract bin and error bar information from them.

Could someone please tell me what I’m missing here? I’ve attached my code at the end (but not the root data files that I’m reading from)

Many thanks,

_ROOT Version: 6.20.00
_Platform: MacOS

#include <string> 

  int fileNumber;
  cout << "How many distances do you want to look at? (Max no. 5)" << endl;
  cin >> fileNumber;

  int energyNumber;
  cout << "How many source energy do you want to look at? (Max no. 3)" << endl;
  cin >> energyNumber;

  int distanceList [] = {0, 1, 10, 50, 100};
  int energyList [] = {100, 500, 1};

  // Create a profile plot                                           
  TCanvas *can = new TCanvas("can","Number of Neutrons");

  TProfile * hprof1 = new TProfile("hprof1","",102,-1, 101,0,3000);
  TProfile * hprof2 = new TProfile("hprof2","",102,-1, 101,0,3000); 
  TProfile * hprof3 = new TProfile("hprof3","",102,-1, 101,0,3000);
  hprof1->GetXaxis()->SetTitle("Source Distance from the Water (m)");
  hprof1->GetYaxis()->SetTitle("Number of Neutrons");
  hprof1->SetTitle("No. of Neutrons Deposited Energy in Water");

  for (int x=0; x<fileNumber; ++x)
    for (int y=0; y<energyNumber; ++y)
      double distance = (double)distanceList[x];
      double sourceEnergy = (double)energyList[y];

      string fname;
      if (y == 0 || y == 1)

      auto file = TFile::Open(fname.c_str());
      cout << "Plotting " << fname << endl;

      // Get Ntuples from file                      
      TNtuple *InfoNtuple = (TNtuple*)file->Get("ParticleInfo"); 
      std::vector<int> * particleID = 0;

      InfoNtuple->SetBranchAddress("ParticleID", &particleID);

      // Loop through events to count up the number of neutrons
      // and add to the profile plot
      int nEntries = (int)InfoNtuple->GetEntries();
      double counter = 0.;
      double meanCount = 0.;

      for (int i=0; i<nEntries; ++i)
        for (int j=0; j<particleID->size(); ++j)      
          if ((*particleID)[j] == 2112) ++counter;
        if (y == 0) hprof1->Fill(distance, counter);
        else if (y == 1) hprof2->Fill(distance, counter);
        else if (y == 2) hprof2->Fill(distance, counter); 
        meanCount += counter;

        counter = 0;
      meanCount /= 1000;
      cout << "For energy "
           << energyList[y]
           << ", the mean no of neutron is " 
           << meanCount 
           << endl;



It should be fine.

Can you try to plot them separately to see if the ranges really match:

   auto C = ne TCanvas("C","C");
   C->cd(1); hprof1->Draw();
   C->cd(2); hprof2->Draw(); 
   C->cd(3); hprof3->Draw(); 

Thanks for the reply. I tried what you’ve suggested, the range in x-axis is definitely the same, the range in z-axis (the vertical axis) is different because each profile plot has different values.

I spoke to someone who used profile plots before and apparently there’s no way to plot multiple of them in one canvas because they are still histograms. The way I’m using to work around it is to fill the profile histos then extract the information using GetBinContent() and GetBinError() and plot using python… It’s not the most elegant solution but it works.

I do not see why the option SAME does not work in your case. Can you post a small reproducer macro ?


THStack *hs =
  new THStack("hs",
              "No. of Neutrons Deposited Energy in Water;Source Distance from the Water (m);Number of Neutrons");