User's Guide for Accessing Level3 Data



This page is intended to document how one accesses data generated by the Level3 trigger algorithms within the context of the DØ analysis framework.  The code samples included have been tested in release p12.01.00.  The following sections are available:
 

General overview:

Accessing  the L3 Chunk
Finding the L3PhysicsResult object you want


Information about specific classes

L3ElePhysicsResults
L3JetsPhysicsResults
L3MuonPhysicsResults
L3TauPhysicsResults

Accessing the L3Chunk

The first step is to access the Level3 chunk from the event.  The procedure for this is similar to how one accesses other chunks:

#include "l3fchunk/L3Chunk.hpp"
#include "l3fchunk/L3ChunkSelector.hpp"
.
.
.
// we're in the analyzeEvent routine now
 L3ChunkSel sl("online");  // I'm not really sure whether "online" or "offline" is wanted....
 edm::TKey<L3Chunk> l3key(sl);
 edm::THandle<L3Chunk> thel3chunk = l3key.find(event);

// always check that the access was successful
 if (!thel3chunk.isValid()) {
       //  don't try to access the chunk in this case!  Give some horrible error message and go away
 }

We now have a pointer to the Level3 chunk, and can begin extracting the L3PhysicsResults objects


Finding the L3PhysicsResult Object You Want

There's a slight complication here, in that there can be several different types of L3PhysicsResults objects within the L3 chunk.  Some objects represent electrons, others muons, and so forth.  So, rather than the chunk containing a single list of L3PhysicsResults objects, there can be several lists (one list of L3ElePhysicsResults objects, another of L3MuonPhysicsResults objects, and so forth). To organize all this information, the chunk contains a map, which can be thought of as an index pointing to the various lists.

So we need to get the map first.  That's straightforward, starting from the chunk:

L3Chunk::L3ChunkPhysToolMap l3map = thel3chunk->getPhysToolMap();

Now we make an iterator to step over the contents of the map:

L3Chunk::L3ChunkPhysToolMap::const_iterator l3mapIter;
        // map has begin() and end() methods that tell us where to start and
       for (l3mapIter= l3map.begin(); l3mapIter != l3map.end(); l3mapIter++) {

Each element of the map is a pair of objects.  In this case, one member is a string describing what
type of L3PhysicsResults object we're dealing with, and the other is the list of L3PhysicsResults
objects.   So we can print out the type of list by doing (note that we're still inside the loop started above):
 cout << l3mapIter->first << endl;  // "first" means first value in the pair

That's nice, but what we really want is the other member of the pair, the list of L3PhysicsResults objects.  As you probably guessed, that's the second part of the pair:

std::list<L3PhysicsResults*> l3l ist= l3mapIter->second;

Now that we have our list of L3PhysicsResults objects, we can interate over it to look at each member.

std::list<L3PhysicsResults*>::const_iterator l3listIter;
         for (l3listIter = l3list.begin(); l3listIter != l3list.end(); l3listIter++) {
      L3PhysicsResults* l3PhysRes = *l3listIter;

Note that l3PhysRes is still a pointer to "generic" L3PhsyicsResults.  Since there is some information common to all L3PhsyicsResults objects, we can access that without knowing whether
we've got an electron or muon or whatever:

        float detEta = l3PhysRes->get_detectorEta();
        float Et     = l3PhysRes->get_ET();
        // there are also other objects of type ZM_QUAL_NAME, but I can't find that class definition...

To get more specific, we will need to know what type of object we have.  Fortunately, all L3PhysicsResults objects are designed to tell us:

l3string theName = l3PhysRes->get_name();
        if (theName == "L3ElePhysicsresults") { // an electron

   // cast the generic L3PhysicsResults pointer to the
                 // specific L3ElePhysicsResults class
   L3ElePhysicsResults* l3ele =
     dynamic_cast<L3ElePhysicsResults*>(l3PhysRes);

   // if there was a problem (like we guessed wrong about what type of object this is), we'll
   // get a null pointer.  Check for this:
   if (l3ele == 0) {
      // Don't try to access it!  Output a dire message and go away.
   }
 

The complete list of L3PhysicsResults objects, and the string returned by get_name() for each, is:
 
 
Type of object get_name() value
L3BTagIPPhysicsResults "L3BTagIPPhysicsresults"
L3ElePhysicsResults "L3ElePhysicsresults"
L3HtPhyiscsResults "L3HtPhysicsresults"
L3JetsPhysicsResults "L3JetsPhysicsresults"
L3McPhysicsResults "L3McPhysicsResults"
L3MEtPhysicsResults "L3MEtPhysicsresults"
L3MuonPhysicsResults "L3MuonPhysicsResults"
L3PhotonPhysicsResults "L3PhotonPhysicsresults"
L3TauPhysicsResults "L3TauPhysicsresults"

Note that it's all straitforward except for some inconsistency in capitalizing the "R" in "Results"!

Documentation specific to each of the classes follows.


L3ElePhysicsResults

First the simple quantities, which are self-explanatory (rememeber that l3ele is a pointer to an L3ElePhysicsResults object).

     float emFraction   = l3ele->get_emFraction();
     float chi2         = l3ele->get_chi2();            // not yet filled
     float isolation    = l3ele->get_isolation();

We can also look for other L3 objects that are associated with this electron candidate:

   const L3CalCluster& calCluster = l3ele->get_CalCluster();  // calorimeter cluster for this electron

L3CalCluster is in the l3fcalcluster package, and the interface is documented in the base class header file L3CalCluster_base.hpp:

   const l3vector<float*>& get_Objects() const;

  const l3vector<L3CalCell> get_Cells(int layer_min=1,
            int layer_max=L3CalConstants::Nilayer) const;
// returns cells in the cluster with layer_min <= ilayer < layer_max
// default is all cells in the cluster
// note that this is layer, not floor index - i.e. to get cells in EM3, use layer_min=3, layer_max=7

  const float& E() const; //Cluster Energy
  const float& Et() const; //Cluster Et
  const float& Px() const; // Cluster "4-momentum" X
  const float& Py() const; // Cluster "4-momentum" Y
  const float& Pz() const; // Cluster "4-momentum" Z
  const float& X() const; //energy-weighted Cluster position X
  const float& Y() const; //energy-weighted Cluster position Y
  const float& Z() const; //energy-weighted Cluster position Z
  const float& Phi() const; //Cluster Phi (from 4-momentum)
  const float& Eta() const; //Cluster Eta (from 4-momentum, wrt vertex)
  const float& Eem() const; //Cluster EM Energy
  const float& ELayer(int l) const; //Cluster Energy per layer
  const float& Profile() const;
  const float& Width(float WidthMinEt=0.) const;
  const float& FloorWidth(int floor) const; // available for floor=1,2,3
  const float& Isolation() const; // Isolation = (Energy in isocone but outside
                isocore)/(Energy in isocore)

  const float& LogWPhi(int CalLayer) const; // "log-weighted" Cluster phi per layer
  const float& LogWEta(int CalLayer) const; // "log-weighted" Cluster eta per layer
  const float& LogWR(int CalLayer) const; // "log-weighted" Cluster radius per layer
  const float& LogWZ(int CalLayer) const; // "log-weighted" Cluster z (wrt 0) per layer

  const float& Vertex_Z() const;
  const float& ConeSize() const;

  L3CalCluster_base& operator+=(L3CalCluster_base c); // merge two clusters
 
 

    bool psMatch       = l3ele->PsMatch();     // "ps" and "cps" mean preshower
     if (psMatch) {
       const L3CPSCluster& psCluster = l3ele->get_PsCluster();
     }

L3CPSCluster is in the l3fcps package, and has the following accessor methods:

  const float& Clus_E() const;
  const float& Clus_phi() const;
  const float& Clus_z() const;
  const float& Clus_Eslc( int ilay ) const;
  const int&   Clus_Nstrp( int ilay) const;
  const float& Clus_Chisq() const;
  const float& Clus_Residual() const;
  const float& Clus_Echisq() const;
 

     bool trackMatch    = l3ele->TrackMatch();
     if (trackMatch) {
       const L3TrackFit& track = l3ele->get_Track();
     }
     bool calTrackMatch = l3ele->CalTrackMatch();
     if (calTrackMatch) {
       const L3TrackFit& calTrack = l3ele->get_CalTrack();
     }
     bool psTrackMatch = l3ele->CpsTrackMatch();
     if (psTrackMatch) {
       const  L3TrackFit& psTrack = l3ele->get_CpsTrack();
     }

L3TrackFit is in package l3ftrack_base, and is well-documented in its .hpp file:

//   A fitted L3 track represented by fit parameters, errors and a chisq
//  value.
//
//   The track helix is separated into two objects, a circular fit in RPhi
//  and a linear fit in RZ. These fits have distinct chisq values and
//  degrees of freedom.  See L3Math for the fitting routines.
//
//   Note that this is a persistent object; it derives from d0_Object
//
//  Interface:
//
//     To retrieve track parameter values:
//
//        l3trackfit.getParam(L3TrackParams::PHI)
//
//     To retrieve element of sigma^2 correlation matrix:
//
//        l3trackfit.getError(L3TrackParams::PHI,L3TrackParams::PHI)
//
//     For chisq information:
//
//        double chisq = l3trackfit.getChiSq();        // total chisq
//        double axialChisq = l3trackfit.getChiSqXY(); // axial fit chisq
//        double stereoChisq = l3trackfit.getChiSqZ(); // stereo fit chisq
//
//     For hit information:
//
//        int nAxialHits = l3trackfit.nHitsXY();
//        int nStereoHits = l3trackfit.nHitsZ();
//
//     To propagate the track to a specific point, assuming a constant B field:
//
//        double x,y,z,r,phi;
//        r = 41.22 // in cm
//        phi = l3ftrackfit.phi_at_r( r );
//        z = l3ftrackfit.z_at_r( r );
//        l3ftrackfit.xy_at_r(r, x, y); // result stored in x,y
 


L3JetsPhysicsResults

This contains some basic information about the jet:

    float emETFraction = l3jet->get_emETfraction();   // fraction of Et found in EM calorimeter
    float icdmgETfraction = l3jet->get_icdmgETfraction();  // fraction of Et found in ICD or massless
                                                                                                  // gaps
    float chETfraction =  l3jet->get_chETfraction();      // fraction of Et found in coarse hadronic
                                                                                           // calorimeter
    float hotCellRatio = l3jet->get_hotcellratio();          // not yet implemented

    const SpaceVector* centroid = l3jet->get_clusterCentroid();
 


L3MuonPhysicsResults

One can start by looking at basic information about the muon:

     int muonRegion = l3muon->get_detectorEta();
     // muonRegion is 0 for WAMUS, -1, 1 for FAMUS N/S resp.

     int nhitmissA = l3muon->get_nhitmissA();
     int nhitmissBC = l3muon->get_nhitmissBC();

     // quantities associated with matched calorimeter track
     float MTCEtrack = l3muon->get_MTC_Etrack();
     float MTCHfrac  = l3muon->get_MTC_Hfrac();

     // quantities associated with matched central track
     float impactXY = l3muon->get_impactXY();
     float signifImpactXY = l3muon->get_signifImpactXY();
 

If more detail is required, you can access additional information about the associated central
track and calorimeter track:

     const L3MuoCalMatchData& calMatchData =
       l3muon->getMuoCalMatchData();
     const L3MuoCentralMatchData& centralMatchData =
       l3muon->getCentralMatchData();

The classes L3MuoCalMatchData and L3MuoCentralMatchData are implemented with
public data members, so they're the equivalent of structures in C.  The list of what's contained
in them can be fouind by looking at:

l3fmuo_local/L3MuoCalMatchData.hpp
l3fmuo_local/L3MuoCentralMatchData.hpp


L3TauPhysicsResults

Basic information about the tau:

     //  get information about this tau
     int seed_algo = l3tau->get_seed_algo();  // 1 = calorimeter-based algorithm used,
                                                                          //  2 = track-based algorithm used
     float emFraction = l3tau->get_emFraction();
     int isolation = l3tau->get_isolation();
     int charge = l3tau->get_charge();
     float width = l3tau->get_width();  // width of calorimeter cluster
     float profile =  l3tau->get_profile()// sum of two leading calorimeter tower Et's over total Et
     int ntracks = l3tau->get_ntracks();

     // information about the energy deposited in the third
     // layer of the EM calorimeter
     float em3_eta = l3tau->get_em3_eta();
     float em3_phi = l3tau->get_em3_phi();
     float em3_E   = l3tau->get_em3_E();

    // Information abot the tracks associated with this tau.
    // Variables are only meaningful for track-based algorithms
    if (seed_algo == 2) {
        if (ntracks > 1) {
            float m01 = l3tau->get_m01(); // inv. mass of two highest-pt tracks
            if (ntracks > 2) {
                float m012 = l3tau()->get_m012(); // inv. mass of three highest-pt tracks
                if (ntracks > 3) {
                    float sumPt3 = l3tau->get_sumpt3(); // total pt of all tracks beyond the top three
                 }
            }
        }
    }

     // the position of the tau cluster centroid
     const SpaceVector* centroid = l3tau->get_clusterCentroid();

We can also access the track and preshower objects associated with this tau if we want more detailed information:

 // get list of all the tracks associated with this tau
      const l3vector<L3TrackFit>* trackList =
        l3tau->get_tracks();
    // can access information about each track by:
    int i;
    for (i=0; i<ntracks; i++) {
        const L3TrackFit* tauTrack = l3tau->get_trackfit(i);
        const L3TrackParams* tauTrackParams
            = l3tau->get_trackpar();
    }

     // get list of preshower clusters associated with this tau
      const l3vector<L3CPSCluster>* clusterList =
        l3tau->get_cpsclusters();


Last updated September 10, 2002 by Erich Varnes