Initialize a 2D array of histograms in a function


ROOT Version: 6.18/04
Platform: Ubuntu 18.04
Compiler: gcc 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)


Dear co-rooters,

I’m trying to initialize a bunch of histograms. What works for my needs is to declare a 2D array h[][] of histograms in my main code and then use a function to initialize them. What I’m doing so far is the following

TString paddle[] = { "none",           //0
                      "Cd",             //1
                      "Cd_Bi",          //2
                      "Cd_2Poly",       //3
                      "Cd_Pb_2Poly",    //4
                      "Cd_Pb_Bi_2Poly", //5
                      "none",           //6
                      "Cd_Bi_2Poly",    //7
                      "Cd",             //8
                      "2Poly",          //9
                      "Pb"              //10               
                    };

//detector numbers

int detector[6] = { 200,
                      2,
                      3,
                      4,
                      6,
                      7
                  };

//void define_histograms(TString name, int number_of_detectors, int number_of_paddles, TH1D h[][number_of_paddles] ){
void define_histograms(TH1D *h, TString name, int number_of_detectors, int number_of_paddles,  ){
	
	for (int det=0; det<number_of_detectors; ++det){
		for (int paddle=0; paddle<number_of_paddles; ++paddle){
			h[det][paddle] = new TH1D(name, "", 10, 0, 10);
		}
	}
	//int r[number_of_detectors][number_of_paddles];
	
	//return r;

}

void analyze(){
        int number_of_detectors = sizeof(detector)/sizeof(detector[0]);
		int number_of_paddles   = *(&paddle+1)-paddle;
		TString name;
		TString title;
		
		TH1D *h_tof_raw[number_of_detectors][number_of_paddles];
		name  = "h_tof_raw";
		//title = "Raw tof; TOF(ns); Counts";
		//for (int det=0; det<number_of_detectors; ++det){
			//for (int paddle=0; paddle<number_of_paddles; ++paddle){
				//h_tof_raw[det][paddle] = new TH1D(name, title, 10, 0, 10);
			//}
		//}
		
		define_histograms(&h_tof_raw[0][0], name, number_of_detectors, number_of_paddles);

}

However when I do that, I get that cannot convert ‘TH1D*’ to ‘double’ in assignment to the point where I initialize the histograms i.e. in the function define_histograms(TH1D*, TString, int, int) at the line

h[det][paddle] = new TH1D(name, "", 10, 0, 10);

Any idea on how to go around that? A similar thing I tried to do in the main code is to initialize the histograms there instead of using a function but eventually I want to create a big amount of different histograms so a function is more convenient.

Any idea on that?

Thanks in advance!

Passing multi-dimensional C arrays around is a little tricky. I would use a nested std::array for the histograms. After paddle and detector are defined, you could declare a type for the histogram 2D array like this:

constexpr int kNumOfPaddles = sizeof(paddle) / sizeof(paddle[0]);
constexpr int kNumOfDetectors = sizeof(detector) / sizeof(detector[0]);
using THTOF = std::array<std::array<TH1D *, kNumOfPaddles>, kNumOfDetectors>;

You’d then use the type to declare h_tof_raw in analyze():

THTOF h_tof_raw;

and also use it in the define_histograms signature, like

void define_histograms(THTOF &h, TString name, int number_of_detectors, int number_of_paddles)

Note that we pass h as a reference (using the ampersand &), so when calling, the function uses the 2D array passed in directly, not a copy of the argument. It’s similar to a pointer.

You might also want to set TH1::AddDirectory(kFALSE); at the beginning of define_histograms (and perhaps TH1::AddDirectory(kTRUE); at the end). This way, the histograms in the 2D array are not registered in the global directory gROOT.

Thanks a lot for your reply!
I think I understand the approach but I have some issues.

I get these errors when trying to compile using .L macro.C++


Error: Symbol array is not defined in current scope  macro.C:23
Error: Symbol array is not defined in current scope  macro.C:23:
Error: Symbol TH1D is not defined in current scope  tmacro.C:23:
Syntax Error: std::array<std::array<TH1D* macro.C:23:
Error: Symbol kNumOfPaddles is not defined in current scope  macro.C:23:
Error: Symbol ,kNumOfDetectors is not defined in current scope  macro.C:23:
Syntax Error: kNumOfPaddles>, kNumOfDetectors> macro.C:23:
 error: expected nested-name-specifier before ‘THTOF’
 error: ‘THTOF’ has not been declared
 error: expected ‘;’ before ‘=’ token
 error: expected unqualified-id before ‘=’ token

I guess it has to do with c++11 so I’m trying to figure out a way to use gSystem->SetMakeSharedLib()

If you compile it, you’d need to #include <array>

What seemed to work is defining a function like so

TH1D*** create_1D_histos(TString name, TString title, TString x_label, TString y_label, int nbins, double low_bin, double high_bin){

	TH1D*** histo = new TH1D**[rows];
    
    for(int det=0; det<rows; det++) {
        histo[det] = new TH1D*[rows]; 
        for(int pad=0; pad<columns; pad++){
        	histo[det][pad] = new TH1D(name.Data(),
        	                           TString::Format("%s;%s;%s", title.Data(), x_label.Data(), y_label.Data()),
        	                           nbins, low_bin, high_bin
        	                          );
			histo[det][pad]->Sumw2();
        }   
    }
    
    return histo;
}

and the call this function in the macro as follows

void main_function(){

    TH1D*** h        = create_1D_histos("h" , "title", "x-axis (units)", "y-axis(units)", 1000, 0, 1000);

}

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.