Association of branches with vectors inside a class

Dear rooters,
I have a problem with association of branches when using vectors inside my class. Here is the code:

void alternative2(TTree* tree1)
{

   class MTEvent
     {public:
        UInt_t num;
        vector<double> et;
        vector<double> * p_et = &et;
        MTEvent()
        : num(0)
         {}
        double getEt(int i) {return et[i];}
        int getSize() {return et.size();}
        int getNum() {return num;}

        Associate(TTree *tree1, Char_t prefix[50], Char_t midfix[50], Char_t suffix[50])
         {Char_t NJets[50], JetEt[50];
          sprintf(NJets,"%s%s%s",prefix,midfix,suffix);
          sprintf(JetEt,"%sEt%s",prefix,suffix);
          TBranch *branch;

          branch = tree1->FindBranch(NJets);
          if (branch!=0) {tree1->SetBranchAddress(NJets,&num); printf("... '%s' \n",NJets);}
          branch = tree1->FindBranch(JetEt);
          if (branch!=0) {tree1->SetBranchAddress(JetEt,&p_et); printf("... '%s' \n",JetEt);}
         }
        ~MTEvent()
         {
         }
     };


    MTEvent *jet = new MTEvent();
    jet->Associate(tree1,"jet","Num","Cone4H1TowerJets");

    Int_t num = tree1->GetEntries();


    for (int k=0; k<num; k++)
      {
       tree1->GetEntry(k);
       int jetNum = jet->getNum();
       int jetSize = jet->getSize();
       printf("jetNum: %i, jetSize: %i \n",jetNum,jetSize);
       for (int j=0; j<jetNum; j++)
         {double value = jet->getEt(j);
          cout << value << endl;
         }
      }
}

In previous versions of trees that contained arrays instead of vectors it worked. It also works if I do the same but outside of the class. Could you please help me?

Thank you, Martin.

Hi,

It looks like, replacing if (branch!=0) {tree1->SetBranchAddress(JetEt,&p_et); printf("... '%s' \n",JetEt);withif (branch!=0) {tree1->SetBranchAddress(JetEt,&et); printf("... '%s' \n",JetEt);}might solve your problem (you may also have to call tree1->GetEntry(0) before calling SetBranchAddress.

Cheers,
Philippe

Hi Philippe,
thank you for your reply. I found that the problem is in my getter. When changing it from:

  double getEt(int i) {return et[i];} 

to

  double getEt(int i) {return (*p_et)[i];}

it started to work without any problems. BUT the problem I have now is that when I want to compile, I recieve the following error:

/direct/usatlas+u/spousta/analysis/./trial2.c: In function `void alternative2(TTree*)':
/direct/usatlas+u/spousta/analysis/./trial2.c:47: error: `alternative2(TTree*)::MTEvent::et' cannot appear in a constant-expression
/direct/usatlas+u/spousta/analysis/./trial2.c:47: error: `&' cannot appear in a constant-expression
/direct/usatlas+u/spousta/analysis/./trial2.c:47: error: ISO C++ forbids initialization of member `p_et'
/direct/usatlas+u/spousta/analysis/./trial2.c:47: error: making `p_et' static
/direct/usatlas+u/spousta/analysis/./trial2.c:47: error: invalid in-class initialization of static data member of non-integral type `std::vector<double, std::allocator<double> >*'

I know that it is not possible to initialize vector inside a class in C++, but I don’t know why this doesn’t work. I need to use this structure:

   std::vector<double> et;
   std::vector<double> * p_et = &et;

inside the class because otherwise I cannot associate vectors with branches. (In my previous analysis I worked with arrays associated inside a class. The motivation is that I can pass an instance of the class that contains all the arrays to different functions performing the analysis over them.) Do you have any idea what to do to prevent such error? Thank you very much,

Martin

… an appendix:
Few minutes ago I found that I can compile successfully when using only:

 std::vector<double> * p_et; 
 ...
 tree1->SetBranchAddress(JetEt,&p_et);  

instead of:

 std::vector<double> et;
 std::vector<double> * p_et = &et;
 ...
 tree1->SetBranchAddress(JetEt,&p_et);

but then running of the algorithm fails (segfaults) at the point when getting an entry (even if I call GetEntry(0) before the association of branches as you suggested).

Hi,

Instead of class MTEvent {public: UInt_t num; vector<double> et; vector<double> * p_et = &et; MTEvent() : num(0) {} ...You should use (because you can not initialize the member in place): class MTEvent {public: UInt_t num; vector<double> et; vector<double> * p_et = &et; MTEvent() : num(0), p_et(&et) {}
OR class MTEvent {public: UInt_t num; vector<double> * p_et; MTEvent() : num(0), p_et(0) {}

[quote]but then running of the algorithm fails (segfaults) at the point when getting an entry (even if I call GetEntry(0) before the association of branches as you suggested).[/quote]This is because the member variable p_et is not initialized and hence has a random value … that the TTree proceeds to use.
Cheers,
Philippe.

Hi Philippe,
thank you! It helped - problem is solved.
Martin