Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-03-28 08:36:07

0001 // ============================================================================
0002 //! \file   ExtractCellIndices.cxx 
0003 //! \author Derek Anderson
0004 //! \date   01.29.2026
0005 // ----------------------------------------------------------------------------
0006 //! \brief
0007 //!   Short macro to illustrate how to extract 
0008 //!   indices from a CellID. Uses calorimeter
0009 //!   hits as the example, but applies to any
0010 //!   object that has a CellID.
0011 //!
0012 //! \usage
0013 //!   Depends on PODIO, EDM4eic, and EDM4hep.
0014 //!   Can be run out of the box inside eic-shell.
0015 //!
0016 //!       $ root -b -q ExtractCellIndices.cxx
0017 // ============================================================================
0018 
0019 #define ExtractCellIndices_cxx
0020 
0021 #include <DD4hep/BitFieldCoder.h>
0022 #include <DD4hep/Detector.h>
0023 #include <DD4hep/IDDescriptor.h>
0024 #include <edm4eic/CalorimeterHitCollection.h>
0025 #include <podio/CollectionBase.h>
0026 #include <podio/Frame.h>
0027 #include <podio/ROOTReader.h>
0028 #include <iostream>
0029 #include <string>
0030 
0031 // default options
0032 static const std::string IFileDefault = "root://dtn-eic.jlab.org//volatile/eic/EPIC/RECO/25.10.4/epic_craterlake/DIS/pythia6.428-1.0/NC/noRad/ep/10x130/q2_10to100/pythia6.428-1.0_NC_noRad_ep_10x130_q2_10to100_ab.0625.eicrecon.edm4eic.root";
0033 static const std::string IReadDefault = "HcalBarrelHits";
0034 static const std::string IHitsDefault = "HcalBarrelRecHits";
0035 
0036 
0037 
0038 // ============================================================================
0039 //! Struct to consolidate user options
0040 // ============================================================================
0041 struct Options {
0042   std::string ifile;  // input file
0043   std::string iread;  // hit collection defining readout (e.g. HcalBarrelHits)
0044   std::string ihits;  // calorimeter hit collection to process (e.g. HcalBarrelRecHits)
0045   uint32_t    nhits;  // max no. of hits to print out
0046 } DefaultOptions = {
0047   IFileDefault,
0048   IReadDefault,
0049   IHitsDefault,
0050   5
0051 };
0052 
0053 
0054 
0055 // ============================================================================
0056 //! Extract indices from cell ID's 
0057 // ============================================================================
0058 void ExtractCellIndices(const Options& opt = DefaultOptions) {
0059 
0060   gErrorIgnoreLevel = kError;
0061   std::cout << "\n  Beginning cell index extraction!" << std::endl;
0062 
0063   // --------------------------------------------------------------------------
0064   // open input
0065   // --------------------------------------------------------------------------
0066 
0067   // open file w/ frame reader
0068   podio::ROOTReader reader = podio::ROOTReader();
0069   reader.openFile( opt.ifile );
0070   std::cout << "    Opened PODIO reader:\n"
0071             << "      " << opt.ifile
0072             << std::endl;
0073 
0074   // --------------------------------------------------------------------------
0075   // initialize DD4hep interfaces
0076   // --------------------------------------------------------------------------
0077 
0078   // initialize detector description
0079   auto detector = dd4hep::Detector::make_unique("");
0080   try {
0081     auto* detConfig = std::getenv("DETECTOR_CONFIG");
0082     auto* detPath   = std::getenv("DETECTOR_PATH");
0083     if (detConfig && detPath) {
0084       detector -> fromCompact(
0085         std::string(detPath) + "/" + std::string(detConfig) + ".xml"
0086       );
0087     } else {
0088       std::cerr << "PANIC: check that DETECTOR_CONFIG and DETECTOR_PATH are set!\n" << std::endl;
0089       exit(-1);
0090     }
0091   } catch(const std::runtime_error& err) {
0092     std::cerr << "PANIC: error initializing detector!\n" << std::endl;
0093     exit(-1);
0094   }
0095   std::cout << "    Initialized detector." << std::endl;
0096 
0097   // set up the ID descriptor
0098   dd4hep::IDDescriptor descriptor;
0099   try {
0100     descriptor  = detector -> readout(opt.iread.data()).idSpec();
0101   } catch (const std::runtime_error& err) {
0102     std::cerr << "PANIC: readout class is not in output!\n" << std::endl;
0103     exit(-1);
0104   }
0105   std::cout << "    Initialized descriptor.\n"
0106             << "    Available fields:"
0107             << std::endl;
0108 
0109   // extract field map and print it out
0110   //   --> NOTE the CellID is a bit field that stores all of
0111   //       the various indices and IDs, i.e. fields, that
0112   //       define a unique cell.
0113   //   --> The no. of bits allocated to each field are set
0114   //       in the "readouts" element in each detector's
0115   //       compact (xml) file
0116   //   --> To extract the value of a field from the CellID:
0117   //         1) First DD4hep masks out all bits NOT
0118   //            allocated for the field, and
0119   //         2) Then it right shifts the remaining bits so
0120   //            that we can convert the value to decimal
0121   //       The "offset" here is how many bits we need to
0122   //       right shift.
0123   auto fields = descriptor.fields(); 
0124   for (const auto& field : fields) {
0125       std::cout << "      name  = "  << field.first << "\n"
0126                 << "      offset = " << field.second
0127                 << std::endl;
0128   }
0129   std::cout << "    Field indices:" << std::endl;
0130 
0131   // grab decoder and test it
0132   //   --> NOTE we'll need the decoder to extract
0133   //       individual fields from a CellID
0134   dd4hep::DDSegmentation::BitFieldCoder* decoder = NULL;
0135   try {
0136     decoder = descriptor.decoder();
0137     for (const auto& field : fields) {
0138       std::cout << "      " << field.first << " = " << decoder -> index(field.first) << std::endl;
0139     }
0140   } catch (const std::runtime_error &err) {
0141     std::cerr << "PANIC: something went wrong grabbing the decoder!\n" << std::endl;
0142     exit(-1);
0143   }
0144 
0145   // --------------------------------------------------------------------------
0146   // frame loop 
0147   // --------------------------------------------------------------------------
0148 
0149   // announce start of frame loop
0150   const uint64_t nFrames = reader.getEntries(podio::Category::Event);
0151   std::cout << "    Starting frame loop: " << nFrames << " frames to process." << std::endl;
0152 
0153   // iterate through frames
0154   for (uint64_t iFrame = 0; iFrame < nFrames; ++iFrame) {
0155 
0156     // announce progress
0157     uint64_t iProg = iFrame + 1;
0158     bool     print = iProg % 100 == 0;
0159     if (print) {
0160       std::cout << "      Processing frame " << iProg << "/" << nFrames << "..." << std::endl;
0161     }
0162 
0163     // grab frame and collection to process
0164     auto        frame = podio::Frame( reader.readNextEntry(podio::Category::Event) );
0165     const auto& hits  = frame.get<edm4eic::CalorimeterHitCollection>(opt.ihits);
0166 
0167     // print up to nhits out -------------------------------------------------- 
0168 
0169     if (print) {
0170       for (uint32_t iHit = 0; const auto& hit : hits) {
0171 
0172         if (iHit >= opt.nhits) {
0173           break;
0174         }
0175 
0176         const auto idObj  = hit.getObjectID();
0177         const auto idCell = hit.getCellID();
0178         std::cout << "        [Hit " << idObj.index << "] cell ID = " << idCell << std::endl;
0179 
0180 
0181         for (const auto& field : fields) {
0182             std::cout << "          " << field.first << " = " << decoder -> get(idCell, field.first) << std::endl;
0183         }
0184         ++iHit;
0185 
0186       }
0187     }
0188   }  // end frame loop
0189   std::cout << "    Frame loop complete!" << std::endl;
0190 
0191   // --------------------------------------------------------------------------
0192   // exit macro 
0193   // --------------------------------------------------------------------------
0194 
0195   std::cout << "  Extraction complete!\n" << std::endl;
0196   return;
0197 
0198 }
0199 
0200 // end ========================================================================