The Jet Collection

We’ll start with the Jet collection, one of the most commonly used collections in ATLAS. Below we’ll look at:

  • Getting jet kinematic properties like \(p_T\) and \(\eta\).

  • Getting the constituents that went into building the jet.

  • Getting the attributes associated with the jet.

The data model used in ATLAS’ xAOD is defined by the C++ objects. func_adl translates the python requests into C++ - so it needs to know about this data model. The func_adl_servicex_xaodr21 package contains that information. For example, when we access a jet’s \(p_T\) with j.pt(), the func_adl system accesses meta-data in the func_adl_servicex_xaodr21 to understand how to make the call, and that its return type is double. With few exceptions, that is how one accesses all methods on the xAOD objects.

The first thing to do is import what we need in our environment. This will be the case at the top of every chapter, but we show it for completness.

  • The datasets. See the DataSet chapter for more information.

  • Various utilities for plotting and array manipulation

  • Some helpers for accessing attributes below (cpp_float, cpp_vfloat)

from config import ds_zee as ds
from config import ds_jz2_exot15
import matplotlib.pyplot as plt
import awkward as ak
import numpy as np
from func_adl_servicex_xaodr21 import cpp_float, cpp_vfloat

Here we return an array of all the jet \(p_T\)’s above 30 GeV. The first SelectMany transforms the event e into a list of jets with the e.Jets(). In this case it returns the default jet collection, properly calibrated and with overlaps removed (see the next chapter on calibration for more information). The SelectMany returns this as a flattened array of jets.

from servicex import ignore_cache
with ignore_cache():
    jets = (ds
            .SelectMany(lambda e: e.Jets())
            .Where(lambda j: (j.pt() / 1000) > 30)
            .Select(lambda j: j.pt() / 1000.0)
            .AsAwkwardArray('JetPt')
            .value())
plt.hist(jets.JetPt, bins=100, range=(0, 100))
plt.xlabel('Jet $p_T$ [GeV]')
plt.ylabel('Number of jets')
_ = plt.title('Jet $p_T$ distribution for $Z\\rightarrow ee$ events')
../_images/jets_5_0.png

Jet Constituents

Jets are composed of TopoClusters in ATLAS, and unfortunately, they are often skimmed away. They are not present, for example, in DAOD_PHYS, which is the skim being used here for most examples. To demonstrate their use we’ll pull from a R21 EXOT15 skim that contains them. Since each jet has an array of topo clusters, and we are just interested in all the TopoClusters, we use two SelectMany calls to flatten both arrays.

topo_clusters = (ds_jz2_exot15
                    .SelectMany(lambda e: e.Jets())
                    .SelectMany(lambda j: j.getConstituents())
                    .Select(lambda tc: tc.pt())
                    .AsAwkwardArray('JetClusterPt')
                    .value()
                )
plt.hist(topo_clusters.JetClusterPt/1000.0, bins=100, range=(0, 20))
plt.xlabel('Jet Cluster $p_T$ [GeV]')
plt.ylabel('Number of jets')
_ = plt.title('Jet Cluster $p_T$ distribution for jets in $Z\\rightarrow ee$ events')
../_images/jets_8_0.png

Jet Moments

Attributes are called moments by the ATLAS Jet/ETMiss group. They are extra information that has been added into the jet object. The Run 2 Moments Page lists all the moments. To access them you’ll need to know the return type explicitly, and parameterize your call to getAttribute appropriately.

Here we grab the EMFrac moment, which is the EM Fraction of the jet. It is a single float for each jet. We specify the type with the cpp_float in the getAttribute[cpp_float]('EMFrac') call. This is translated into C++ that looks something like j->getAttribute<float>("EMFrac").

moments = (ds
           .SelectMany(lambda e: e.Jets())
           .Where(lambda j: (j.pt() / 1000) > 30)
           .Select(lambda j: j.getAttribute[cpp_float]('EMFrac'))
           .AsAwkwardArray('emfrac')
           .value())
plt.hist(moments.emfrac, bins=100, range=(0, 1.1))
plt.xlabel('EM Fraction')
plt.ylabel('Number of jets')
_ = plt.title('EM Fraction of jets in JZ3 events')
../_images/jets_11_0.png

More complex objects can come back as well. For example, vectors of floats (std::vector<float>). Here is a sample with the sum track \(p_T\) when track \(p_T > 500\) MeV.

sum_pt = (ds
          .SelectMany(lambda e: e.Jets("AntiKt4EMPFlowJets"))
          .Where(lambda j: (j.pt() / 1000) > 31)
          .SelectMany(lambda j: j.getAttribute[cpp_vfloat]('SumPtTrkPt500'))
          .AsAwkwardArray('sum_pt')
          .value())
plt.hist(sum_pt.sum_pt/1000.0, bins=100, range=(0, 4))
plt.xlabel('Sum track $p_T$ [GeV]')
plt.ylabel('Number of jets')
plt.yscale('log')
_ = plt.title('Sum Track $p_T$ for tracks over 500 MeV in JZ3 events')
../_images/jets_14_0.png

As with everything else in the ATLAS data model, even if they are reconstructed and associated with the jet, they can be stripped out with slimming - so just because they are declared on the Run 2 Moments page, it doesn’t mean they actually exist in the data file you are looking at.

This describes the basics of how to access jets in the ATLAS xAOD. The next chapter will continue discussing jets, focusing on how calibrations are handled by the func_adl backend.

The Data Model

The data model when this documentation was last built was:

from func_adl_servicex_xaodr21.xAOD.jet_v1 import Jet_v1
help(Jet_v1)
Help on class Jet_v1 in module func_adl_servicex_xaodr21.xAOD.jet_v1:

class Jet_v1(builtins.object)
 |  A class
 |  
 |  Methods defined here:
 |  
 |  btagging(self) -> 'func_adl_servicex_xaodr21.xAOD.btagging_v1.BTagging_v1'
 |      A method
 |  
 |  btaggingLink(self) -> 'func_adl_servicex_xaodr21.elementlink_datavector_xaod_btagging_v1__.ElementLink_DataVector_xAOD_BTagging_v1__'
 |      A method
 |  
 |  clearDecorations(self) -> 'bool'
 |      A method
 |  
 |  constituentLinks(self) -> 'func_adl_servicex_xaodr21.vector_elementlink_datavector_xaod_iparticle___.vector_ElementLink_DataVector_xAOD_IParticle___'
 |      A method
 |  
 |  e(self) -> 'float'
 |      A method
 |  
 |  eta(self) -> 'float'
 |      A method
 |  
 |  getConstituents(self) -> 'func_adl_servicex_xaodr21.xAOD.jetconstituentvector.JetConstituentVector'
 |      A method
 |  
 |  getSizeParameter(self) -> 'float'
 |      A method
 |  
 |  hasNonConstStore(self) -> 'bool'
 |      A method
 |  
 |  hasStore(self) -> 'bool'
 |      A method
 |  
 |  index(self) -> 'int'
 |      A method
 |  
 |  m(self) -> 'float'
 |      A method
 |  
 |  numConstituents(self) -> 'int'
 |      A method
 |  
 |  p4(self) -> 'func_adl_servicex_xaodr21.tlorentzvector.TLorentzVector'
 |      A method
 |  
 |  phi(self) -> 'float'
 |      A method
 |  
 |  pt(self) -> 'float'
 |      A method
 |  
 |  px(self) -> 'float'
 |      A method
 |  
 |  py(self) -> 'float'
 |      A method
 |  
 |  pz(self) -> 'float'
 |      A method
 |  
 |  rapidity(self) -> 'float'
 |      A method
 |  
 |  rawConstituent(self, i: 'int') -> 'func_adl_servicex_xaodr21.xAOD.iparticle.IParticle'
 |      A method
 |  
 |  usingPrivateStore(self) -> 'bool'
 |      A method
 |  
 |  usingStandaloneStore(self) -> 'bool'
 |      A method
 |  
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |  
 |  auxdataConst
 |      A method
 |  
 |  getAttribute
 |      A method
 |  
 |  isAvailable
 |      A method
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)
from func_adl_servicex_xaodr21.xAOD.jetconstituent import JetConstituent
help(JetConstituent)
Help on class JetConstituent in module func_adl_servicex_xaodr21.xAOD.jetconstituent:

class JetConstituent(builtins.object)
 |  A class
 |  
 |  Methods defined here:
 |  
 |  e(self) -> 'float'
 |      A method
 |  
 |  eta(self) -> 'float'
 |      A method
 |  
 |  isSpacelike(self) -> 'bool'
 |      A method
 |  
 |  isTimelike(self) -> 'bool'
 |      A method
 |  
 |  m(self) -> 'float'
 |      A method
 |  
 |  phi(self) -> 'float'
 |      A method
 |  
 |  pt(self) -> 'float'
 |      A method
 |  
 |  rapidity(self) -> 'float'
 |      A method
 |  
 |  rawConstituent(self) -> 'func_adl_servicex_xaodr21.xAOD.iparticle.IParticle'
 |      A method
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)

Further Information