Re: [ROOT] Arrays of 2D histograms

From: Christian Holm Christensen (cholm@hehi03.nbi.dk)
Date: Wed Aug 21 2002 - 22:09:43 MEST


On Wed, 21 Aug 2002 14:35:45 -0400
"William Love" <love@bnl.gov> wrote
concerning "[ROOT] Arrays of 2D histograms":
> Hello root
>   I want to divide track data among identical TH2D's according to
>  for example, the vertex z.   This would be easiest if I could make and
>  address an array of TH2D's  I tried:
> 
>  *** Start at Date : Wed Aug 21 14:10:58 2002
> QAInfo:You are using STAR_LEVEL : dev, ROOT_LEVEL : 3.02.07 and node :
> rcas6006.rcf.bnl.gov

> root.exe [0] TH2D Same[8]("b","b",50, 0, 10, 50, 0, 10)

First off, this is not valid C++.  To test if something is valid, try
and compile it properly e.g., doing: 

  root [0] .x foo.C++ 

(Hi Rene :-)  You'll see the error:

  initializing array with parameter list

So far so good. Now, taking out the parameter list, like 

  TH2D same[8]; 

still leaves you with a problem though it OK C++.   

> root.exe [1] Same[2].SetName("number3")
> 
>  *** Break *** segmentation violation
> 


The problem is, that you initialise each elment of the array with the
default constructor (CTOR), which does not do all the allocations you
need.  

>   Where do I go wrong?

You need to use a named CTOR and specify all the stuff you need to.
One way of doing this, is to have a pointer to a pointer array:

  // Allocate memory for 8 pointers, each pointing to a TH2D. 
  // (this is 8 long's, so it isn't as bad as it looks)   
  TH2D** same = new TH2D*[8];

  // Now we need to initialise each pointer in turn 
  for (Int_t i = 0; i < 8; i++) 
    same[i] = new TH1D(Form("same%02d", i), Form("same%02d", i), 
		50, 0, 10, 50, 0, 10); 

   // Do some work 
   .... 
   for (Int_t i = 0; i < 8; i++) 
     same[i]->Fill(x[i], y[i], w[i]);

   // Now we want to deallocate the array.  We have to free the memory
   // of each pointer explicitly, or we're in trouble. 
  for (Int_t i = 0; i < 8; i++) 
    delete same[i];
  // And finally we free the 8 pointers: 
  delete same; 
   
Now, if you think this looks ugly and are about to say `Hay, that
was easier in Fortran', it's because you're partially right.  The
thing to remember is, that C++ (inheriting it from C) is intrinsicly
bad at handling arrays.  Instead, one would either implement a
specialised class (TList, TObjArray, ...) or use a templated class,
like and STL container.  The latter is probably the best thing to do: 

  std::vector<TH2D*> same; 
  same[0] = new TH2D(...);

This is acually much safer (less error prone) than the double pointer
stuff above.  The choice of STL container depends on what you want to
do - check out the SGI STL documentation that probably ships with your
favorite Linux distribution. 

> I was up all night wondering where the sun went, then it dawned on me.

Don't you just hate that? 

Yours, 

 ____ |  Christian Holm Christensen 
  |_| |	 -------------------------------------------------------------
    | |	 Address: Sankt Hansgade 23, 1. th.  Phone:  (+45) 35 35 96 91
     _|	          DK-2200 Copenhagen N       Cell:   (+45) 24 61 85 91
    _|	          Denmark                    Office: (+45) 353  25 305
 ____|	 Email:   cholm@nbi.dk               Web:    www.nbi.dk/~cholm
 | |



This archive was generated by hypermail 2b29 : Sat Jan 04 2003 - 23:51:05 MET