Get Number of Divisions in a TCanvas

ROOT Version: v6.14.06
Platform: Ubuntu 16.04.6 LTS
Compiler: g++ (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609


I would like to have a way of obtaining the number of “divisions” in a TCanvas. I looked in the ROOT documentation, and I could not find any relevant member functions in TCanvas. I say “divisions” but I’m not sure that is the right word. But I think “pads” is not the right word either in my case.

Here is my minimal example that shows the problem:

#include <cassert>

#include "TCanvas.h"

int get_number_of_pads(TCanvas* canvas) {

  int number_of_pads = 0;

  for (const auto& object : *canvas->GetListOfPrimitives()) {
    if (object->InheritsFrom(TVirtualPad::Class())) {
      ++number_of_pads;
    }
  }

  return number_of_pads;

}

void minimal() {

  TCanvas* c1 = new TCanvas();
  c1->Divide(2, 2);

  TCanvas* c2 = new TCanvas();
  c2->Divide(4, 4);

  TCanvas* c3 = new TCanvas();

  assert(get_number_of_pads(c1) == 4);
  assert(get_number_of_pads(c2) == 16);
  assert(get_number_of_pads(c3) == 1); // This fails                                                                                                                                                                                                                                  

}

I know why the last assert fails: the TList from GetListOfPrimitives is empty.

If there is some ROOT functionality that already exists, please let me know. Otherwise, I basically would like a function get_number_of_divisions that passes all of my assert statements. For c3 in the minimal example, it has one “division” or one “drawing space” even though it has zero “pads” (if that makes sense). Just curious if there is a way to do this without the obvious condition at the end of the function:

  if (number_of_pads == 0) {                                                                                                                                                                                                                                                          
    number_of_pads = 1;
  }

Yes, you mean the number of pads…
There is no such functionality.
What is the use case ?

Thanks for the reply!

My minimal example is based off of this, which is supposed to count the number of pads. Because my minimal example fails for c3, I started to think that maybe I didn’t know exactly what constitutes a pad.

My use case is wanting to loop over the pads in a canvas and do some tinkering to those pads. It would work whether the canvas was divided or not. I would have thought a simple function like TCanvas::GetNumberOfPads would exist for this.

I guess I’ll have to catch the edge case (undivided canvas) myself?

if (number_of_pads == 0) {                                                                                                                                                                                                                                                          
  number_of_pads = 1;
}

It works for me.

I did:

Int_t countpads(TVirtualPad *pad) {
   //count the number of pads in pad
   if (!pad) return 0;
   Int_t npads = 0;
   TObject *obj;
   TIter next(pad->GetListOfPrimitives());
   while ((obj = next())) {
      if (obj->InheritsFrom(TVirtualPad::Class())) npads++;
   }
   return npads;
}

void npads() {
   TCanvas* c1 = new TCanvas();
   c1->Divide(2, 2);
   printf("%d\n", countpads(c1));
}

it gives me:

% root npads.C
   ------------------------------------------------------------------
  | Welcome to ROOT 6.23/01                        https://root.cern |
  | (c) 1995-2020, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for macosx64 on Sep 17 2020, 07:58:14                      |
  | From heads/master@v6-23-01-1248-gb96280beb0                      |
  | With Apple clang version 12.0.0 (clang-1200.0.32.2)              |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'       |
   ------------------------------------------------------------------

root [0] 
Processing npads.C...
4
root [1] 

Correct… and if you comment out the line

c1->Divide(2, 2);

the function returns 0. That is the whole point of my post…

Based on your “Yes, you mean the number of pads…” in your first reply, I would think an undivided canvas would have a single pad. Is this correct or not?

Yes … and that’s normal, isn’t it. ? … there is no pads in the Canvas in that case …

Then why does this work?

void minimal() {

  TCanvas* canvas = new TCanvas("canvas", "canvas");
  TVirtualPad* pad = canvas->cd();
  std::cout << pad->GetName() << std::endl;

}

It’s an undivided canvas, and ROOT thinks there is a pad?

A TCanvas is a TPad … that’s why.

and countpads returns the number of pad inside a TCanvas.

I guess it’s something I need keep clear/straight in my head. Thank you very much for your help today. It is greatly appreciated.