Example CalDigi Analysis

Note:  The following code was taken directly from RootTreeAnalysis in the RootAnalysis package stored in Offline's CVS repository.
In this context, the variable, evt, is a DigiEvent object which was filled in RootTreeAnalysis::Go( ) method.  All file handling is done within the initialization of the RootTreeAnalysis object and is not shown here.

The complete documentation of the digiRootData library which defines DigiEvent and all digitization (detector) classes can be found at:
http://confluence.slac.stanford.edu/display/WB/digiRootData
 

Code Snippet Description
void RootTreeAnalysis::DigiCal() {
    // Purpose and Method:  Process on CAL digi event
       
    const TObjArray* calDigiCol = evt->getCalDigiCol();
    if (!calDigiCol) return;

    Int_t nCalDigi = calDigiCol->GetEntries();
    ((TH1F*)GetObjectPtr("CALDIGICOUNT"))->Fill((Float_t)nCalDigi);
   
    Int_t nLayer[8]={0,0,0,0,0,0,0,0};
    Float_t eLayer[8]={0.,0.,0.,0.,0.,0.,0.,0.};
    Float_t eTotal = 0.;

 
 
Retrieve the full collection of CalDigi objects from DigiEvent.

Determine how many CalDigi objects exist for this event.

Fill a histogram named CALDIGICOUNT with the number of CalDigi events.

Initialize some arrays used to store details.

   TIter calDigiIter(calDigiCol);
    CalDigi *c = 0;
   
    while (c = (CalDigi*)calDigiIter.Next()) {

        // Assuming Best Range and checking only the first readout
        const CalXtalReadout* cRo=c->getXtalReadout(0);
        Float_t adcP = cRo->getAdc(CalXtalId::POS);
        Float_t adcN = cRo->getAdc(CalXtalId::NEG);

        // ligh asymmetry
        Float_t asy = 1.;
        if (adcP + adcN == 200.)
          asy = 1.;
        else
          asy = (adcP-adcN)/(adcP+adcN-200.);

        Float_t eAve = (adcP + adcN)/2.;

        ((TH1F*)GetObjectPtr("CALEAVE"))->Fill(eAve);
        ((TH1F*)GetObjectPtr("CALADC"))->Fill((float)cRo->getAdc(CalXtalId::POS));
        ((TH1F*)GetObjectPtr("CALADC"))->Fill((float)cRo->getAdc(CalXtalId::NEG));
        ((TH1F*)GetObjectPtr("CALRANGE"))->Fill(cRo->getRange(CalXtalId::POS));
        ((TH1F*)GetObjectPtr("CALRANGE"))->Fill(cRo->getRange(CalXtalId::NEG));

        // Retrieve the identifer for this crystal
        CalXtalId id = c->getPackedId();
        Int_t layer = id.getLayer();
        Int_t tower = id.getTower();
        Int_t column = id.getColumn();
        ((TH1F*)GetObjectPtr("CALLAYER"))->Fill(layer);
        ((TH1F*)GetObjectPtr("CALTOWER"))->Fill(tower);
        ((TH1F*)GetObjectPtr("CALCOLUMN"))->Fill(column);
       
        nLayer[layer] += 1;
        eLayer[layer] += eAve;
        eTotal += eAve;
    }
   
 
Create a ROOT TIter that allows us to iterate over the collection of CalDigis, the while loop uses the TIter to control the loop, and the object named c, contains the CalDigi pointer.

Retrieve the first crystal readout - which is assumed to be the "BEST Range"

Find the ADC values for both ends:  Positive and Negative.

Calculate the light asymmetry.

Fill a number of histograms.

Determine the full CalXtalId for this CalDigi which is packed.  A number of methods are available to unpack the identifier:  getLayer, getTower, getColumn.  And fill three more histograms with the id fields.

Update the arrays: nLayer, eLayer, and eTotal based on the values we have already retrieved during this iteration of this loop.

  ((TH1F*)GetObjectPtr("CALEAVETOTAL"))->Fill(eTotal);
   
    ((TH1F*)GetObjectPtr("CALELYR0"))->Fill(eLayer[0]);
    ((TH1F*)GetObjectPtr("CALELYR1"))->Fill(eLayer[1]);
    ((TH1F*)GetObjectPtr("CALELYR2"))->Fill(eLayer[2]);
    ((TH1F*)GetObjectPtr("CALELYR3"))->Fill(eLayer[3]);
    ((TH1F*)GetObjectPtr("CALELYR4"))->Fill(eLayer[4]);
    ((TH1F*)GetObjectPtr("CALELYR5"))->Fill(eLayer[5]);
    ((TH1F*)GetObjectPtr("CALELYR6"))->Fill(eLayer[6]);
    ((TH1F*)GetObjectPtr("CALELYR7"))->Fill(eLayer[7]);
   
    ((TH1F*)GetObjectPtr("CALNLYR0"))->Fill(nLayer[0]);
    ((TH1F*)GetObjectPtr("CALNLYR1"))->Fill(nLayer[1]);
    ((TH1F*)GetObjectPtr("CALNLYR2"))->Fill(nLayer[2]);
    ((TH1F*)GetObjectPtr("CALNLYR3"))->Fill(nLayer[3]);
    ((TH1F*)GetObjectPtr("CALNLYR4"))->Fill(nLayer[4]);
    ((TH1F*)GetObjectPtr("CALNLYR5"))->Fill(nLayer[5]);
    ((TH1F*)GetObjectPtr("CALNLYR6"))->Fill(nLayer[6]);
    ((TH1F*)GetObjectPtr("CALNLYR7"))->Fill(nLayer[7]);
   
}
Fill the remaining CalDigi histograms.
    // example of filling a simple tree
    Float_t digiArr[2] = { (Float_t)nCalDigi, eTotal };
    ((TNtuple*)GetObjectPtr("calDigiTup"))->Fill(digiArr);
 
Example of filling a simple ntuple.

 

If you desire to download this piece of code - here is a full copy:

void RootTreeAnalysis::DigiCal() {
    // Purpose and Method:  Process on CAL digi event
       
    const TObjArray* calDigiCol = evt->getCalDigiCol();
    if (!calDigiCol) return;

    Int_t nCalDigi = calDigiCol->GetEntries();
    ((TH1F*)GetObjectPtr("CALDIGICOUNT"))->Fill((Float_t)nCalDigi);
   
    Int_t nLayer[8]={0,0,0,0,0,0,0,0};
    Float_t eLayer[8]={0.,0.,0.,0.,0.,0.,0.,0.};
    Float_t eTotal = 0.;

    TIter calDigiIter(calDigiCol);
    CalDigi *c = 0;
   
    while (c = (CalDigi*)calDigiIter.Next()) {

        // Assuming Best Range and checking only the first readout
        const CalXtalReadout* cRo=c->getXtalReadout(0);
        Float_t adcP = cRo->getAdc(CalXtalId::POS);
        Float_t adcN = cRo->getAdc(CalXtalId::NEG);

        // ligh asymmetry
        Float_t asy = 1.;
        if (adcP + adcN == 200.)
          asy = 1.;
        else
          asy = (adcP-adcN)/(adcP+adcN-200.);

        Float_t eAve = (adcP + adcN)/2.;

        ((TH1F*)GetObjectPtr("CALEAVE"))->Fill(eAve);
        ((TH1F*)GetObjectPtr("CALADC"))->Fill((float)cRo->getAdc(CalXtalId::POS));
        ((TH1F*)GetObjectPtr("CALADC"))->Fill((float)cRo->getAdc(CalXtalId::NEG));
        ((TH1F*)GetObjectPtr("CALRANGE"))->Fill(cRo->getRange(CalXtalId::POS));
        ((TH1F*)GetObjectPtr("CALRANGE"))->Fill(cRo->getRange(CalXtalId::NEG));

        // Retrieve the identifer for this crystal
        CalXtalId id = c->getPackedId();
        Int_t layer = id.getLayer();
        Int_t tower = id.getTower();
        Int_t column = id.getColumn();
        ((TH1F*)GetObjectPtr("CALLAYER"))->Fill(layer);
        ((TH1F*)GetObjectPtr("CALTOWER"))->Fill(tower);
        ((TH1F*)GetObjectPtr("CALCOLUMN"))->Fill(column);
       
        nLayer[layer] += 1;
        eLayer[layer] += eAve;
        eTotal += eAve;
    }
   
    ((TH1F*)GetObjectPtr("CALEAVETOTAL"))->Fill(eTotal);
   
    ((TH1F*)GetObjectPtr("CALELYR0"))->Fill(eLayer[0]);
    ((TH1F*)GetObjectPtr("CALELYR1"))->Fill(eLayer[1]);
    ((TH1F*)GetObjectPtr("CALELYR2"))->Fill(eLayer[2]);
    ((TH1F*)GetObjectPtr("CALELYR3"))->Fill(eLayer[3]);
    ((TH1F*)GetObjectPtr("CALELYR4"))->Fill(eLayer[4]);
    ((TH1F*)GetObjectPtr("CALELYR5"))->Fill(eLayer[5]);
    ((TH1F*)GetObjectPtr("CALELYR6"))->Fill(eLayer[6]);
    ((TH1F*)GetObjectPtr("CALELYR7"))->Fill(eLayer[7]);
   
    ((TH1F*)GetObjectPtr("CALNLYR0"))->Fill(nLayer[0]);
    ((TH1F*)GetObjectPtr("CALNLYR1"))->Fill(nLayer[1]);
    ((TH1F*)GetObjectPtr("CALNLYR2"))->Fill(nLayer[2]);
    ((TH1F*)GetObjectPtr("CALNLYR3"))->Fill(nLayer[3]);
    ((TH1F*)GetObjectPtr("CALNLYR4"))->Fill(nLayer[4]);
    ((TH1F*)GetObjectPtr("CALNLYR5"))->Fill(nLayer[5]);
    ((TH1F*)GetObjectPtr("CALNLYR6"))->Fill(nLayer[6]);
    ((TH1F*)GetObjectPtr("CALNLYR7"))->Fill(nLayer[7]);
   
    // example of filling a simple tree
    Float_t digiArr[2] = { (Float_t)nCalDigi, eTotal };
    ((TNtuple*)GetObjectPtr("calDigiTup"))->Fill(digiArr);
}