Organizing lots of new classes for use in ROOT macros?

Hi. I’m picking up a new project that is taking its first steps and would like to start writing analysis tools in the form of a set of classes like EvtLoader, PulseIdentifier, PeakFinder, etc. I’m clueless as to how to organize all of this code for the project, and even more so for how to integrate all of it together. I’d like to be able to use the classes in two ways:

  1. Write root macros like the following that can be executed with a “root MyMacroAnalysis.C+”:

#include "PulseArray.hh" #include "EvtLoader.hh" { EvtLoader* evtloader = new EvtLoader("data20101009.evt"); evtloader->LoadAll(); PulseArray* pulse_array = evtloader->GetPulses(); // More analysis... }
2) Interactively at the interpreter.

I would like to get method 1) set up first so let’s ignore 2). In my short tests where I’ve attempted this with toy classes I’ve not succeeded. Let’s use the following as an example:

pmt.h

[code]#ifndef PMT_H
#define PMT_H 1

class PMT {
double gain, voltage;
public:
PMT();
double GetGain();
double GetVoltage();

    void SetGain(double g);
    void SetVoltage(double v);

// Put in here for root testing to import the class.
ClassDef(PMT,1);

};

#endif
[/code]
pmt.C

[code]#include “pmt.h”

ClassImp(PMT)

using namespace std;

double PMT::GetGain() {return gain;}
double PMT::GetVoltage() {return voltage;}

void PMT::SetGain(double g) {gain=g;}
void PMT::SetVoltage(double v) {voltage=v;}
[/code]

test_pmt_class.C

[code]#include
#include “pmt.h”

PMT *pmt = new PMT;
pmt->SetVoltage(900);
pmt->SetGain(2e6);

double voltage = pmt->GetVoltage();
double gain= pmt->GetGain();

cout << "The voltage is " << voltage
<< " and the gain is " << gain << “.” <<endl;
}
[/code]

Running with “root test_pmt_class.C+” returns:

root [0] Processing test_pmt_class.C+... root [1]

The namespace is empty, nothing was printed, I don’t have access to my PMT class, and I clearly don’t understand how this kind of structure can be used to put together an analysis! What am I missing (conceptually) and what do I need to change to make a class-based analysis toolset work for me? Thanks a lot for your help.

Ahh, I might have figure something out. Stay tuned for an update. If anyone could give feedback on my method that would be nice.

I’ll repost pmt.h, pmt.C, and test_pmt_class.C:

#ifndef PMT_H
#define PMT_H 1


class PMT {
    double gain, voltage;
    public:
        PMT();
        double GetGain();
        double GetVoltage();

        void SetGain(double g);
        void SetVoltage(double v);

    // Put in here for root testing to import the class.
    ClassDef(PMT,1);
};

#endif
#include "pmt.h"

ClassImp(PMT)

using namespace std;

PMT::PMT() {}
double PMT::GetGain() {return gain;}
double PMT::GetVoltage() {return voltage;}

void PMT::SetGain(double g) {gain=g;}
void PMT::SetVoltage(double v) {voltage=v;}
{

gROOT->ProcessLine(".L pmt.C+");
PMT *pmt = new PMT;
pmt->SetVoltage(900);
pmt->SetGain(2e6);

double voltage = pmt->GetVoltage();
double gain= pmt->GetGain();

cout << "The voltage is " << voltage
     << " and the gain is " << gain << "." <<endl;

}

The big change was that the class is loaded in the macro with the ProcessLine method. Now the cout statements are processed and I’m even left with the pmt instance to play with in the interpreter. Great. I also added the default constructor to pmt.C.

So, now it basically works, but is this how I should be going about it? When I start adding more (real) classes, I’ll need a flurry of ProcessLine’s to load the classes, or I could change the ProcessLine in test_pmt_class.C to:

gROOT->ProcessLine(".x MyRootClasses.C");

and the new MyRootClasses.C file could contain:

{ gROOT->ProcessLine(".L pmt.C+"); gROOT->ProcessLine(".L Class1.C+"); gROOT->ProcessLine(".L Class2.C+"); gROOT->ProcessLine(".L Class3.C+"); gROOT->ProcessLine(".L Class4.C+"); }

This seems like an odd way to use all of my classes. Or is this fine?

It is a fine way of doing so. If you wanted just one library, then instead you would need a wrapper source file like:[code]
#include “class1.C”
#include “class2.C”

#ifdef MAKECINT
#pragma link C++ class class1+;
#pragma link C++ class class2+;
#endif[/code]and load this single via ACLiC.

Cheers,
Philippe.