Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:14:09

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 
0014 // Framework include files
0015 #include <DD4hep/Printout.h>
0016 #include <DDDigi/DigiData.h>
0017 #include <DDDigi/DigiSegmentationTool.h>
0018 
0019 // C/C++ include files
0020 #include <sstream>
0021 
0022 using namespace dd4hep::digi;
0023 
0024 namespace  {
0025   void scan_detector(const DigiSegmentationTool& tool,
0026                      const std::string& split_by,
0027                      std::map<dd4hep::VolumeID, std::pair<dd4hep::DetElement, dd4hep::VolumeID> >& splits,
0028                      dd4hep::DetElement de, dd4hep::VolumeID vid, dd4hep::VolumeID mask)   {
0029     dd4hep::PlacedVolume plc = de.placement();
0030     const auto&      new_ids = plc.volIDs();
0031     dd4hep::VolumeID new_vid = vid;
0032     dd4hep::VolumeID new_msk = mask;
0033     if ( !new_ids.empty() )   {
0034       new_vid |= tool.iddescriptor.encode(new_ids);
0035       new_msk |= tool.iddescriptor.get_mask(new_ids);
0036       for (const auto& id : new_ids)   {
0037         if ( id.first == split_by )   {
0038           splits.emplace(new_vid, std::make_pair(de, id.second));
0039           return;
0040         }
0041       }
0042     }
0043     for ( const auto& c : de.children() )
0044       scan_detector(tool, split_by, splits, c.second, new_vid, new_msk);
0045   }
0046 }
0047 
0048 /// Split field name
0049 const std::string& DigiSegmentContext::name()  const  {
0050   if ( this->field )  {
0051     return this->field->name();
0052   }
0053   throw std::runtime_error("Invalid field name!");
0054 }
0055 
0056 /// Split field name
0057 const char* DigiSegmentContext::cname()  const  {
0058   return this->field ? this->field->name().c_str() : "";
0059 }
0060 
0061 /// Full identifier (field + id)
0062 std::string DigiSegmentContext::identifier(uint32_t id)  const   {
0063   std::stringstream str;
0064   if ( this->field )   {
0065     str << this->field->name() << "." << id;
0066   }
0067   return str.str();
0068 }
0069 
0070 /// Initializing constructor
0071 DigiSegmentationTool::DigiSegmentationTool(Detector& desc)
0072   : description(desc)
0073 {
0074 }
0075 
0076 /// Setup tool to handle a given detector of the geometry
0077 void DigiSegmentationTool::set_detector(const std::string& det_name)    {
0078   const char* det = det_name.c_str();
0079   this->detector = this->description.detector(det_name);
0080   if ( !this->detector.isValid() )   {
0081     except("DigiSegmentationTool",
0082            "FAILED: Cannot access subdetector %s from the detector description.", det);
0083   }
0084   this->sensitive = this->description.sensitiveDetector(det_name);
0085   if ( !sensitive.isValid() )   {
0086     except("DigiSegmentationTool",
0087            "FAILED: Cannot access sensitive detector for %s.", det);
0088   }
0089   this->iddescriptor = this->sensitive.idSpec();
0090   if ( !this->iddescriptor.isValid() )   {
0091     except("DigiSegmentationTool",
0092            "FAILED: Cannot access ID descriptor for detector %s.", det);
0093   }
0094 }
0095 
0096 /// Access the readout collection keys
0097 std::vector<std::string> DigiSegmentationTool::collection_names()   const   {
0098   if ( this->sensitive.isValid() )    {
0099     Readout rd = this->sensitive.readout();
0100     std::vector<std::string> names = rd.collectionNames();
0101     if ( names.empty() ) names.emplace_back(rd.name());
0102     return names;
0103   }
0104   except("DigiSegmentationTool",
0105          "+++ collection_names: Readout not valid. Is the proper detector set ?");
0106   return {};
0107 }
0108 
0109 /// Access the readout collection keys
0110 std::vector<Key> DigiSegmentationTool::collection_keys()   const   {
0111   return collection_keys(0x0);
0112 }
0113 
0114 /// Access the readout collection keys
0115 std::vector<Key> DigiSegmentationTool::collection_keys(Key::mask_type mask)   const   {
0116   std::vector<Key> keys;
0117   std::vector<std::string> names = collection_names();
0118   for( const auto& collection : names )
0119     keys.emplace_back(Key(collection, mask));
0120   return keys;
0121 }
0122 
0123 /// Access the readout collection keys
0124 std::vector<Key> 
0125 DigiSegmentationTool::collection_keys(const std::vector<std::string>& detectors) const  {
0126   std::vector<Key> keys;
0127   for( const auto& det : detectors )   {
0128     DigiSegmentationTool tool(this->description);
0129     tool.set_detector(det);
0130     auto det_keys = tool.collection_keys(0x0);
0131     keys.insert(keys.end(), det_keys.begin(), det_keys.end());
0132   }
0133   return keys;
0134 }
0135 
0136 /// Access the readout collection keys
0137 std::vector<Key> 
0138 DigiSegmentationTool::collection_keys(const std::vector<std::string>& detectors,
0139                                       Key::mask_type mask)   const
0140 {
0141   std::vector<Key> keys;
0142   for( const auto& det : detectors )   {
0143     DigiSegmentationTool tool(this->description);
0144     tool.set_detector(det);
0145     auto det_keys = tool.collection_keys(mask);
0146     keys.insert(keys.end(), det_keys.begin(), det_keys.end());
0147   }
0148   return keys;
0149 }
0150 
0151 /// Create a split context depending on the segmentation field
0152 DigiSegmentContext 
0153 DigiSegmentationTool::split_context(const std::string& split_by)  const {
0154   DigiSegmentContext splitter;
0155   splitter.cell_mask = ~0x0UL;
0156   splitter.detector  = this->detector;
0157   splitter.idspec    = this->iddescriptor;
0158   for(const auto& f : this->iddescriptor.fields())   {
0159     const BitFieldElement* e = f.second;
0160     if ( e->name() == split_by )   {
0161       splitter.field      = e;
0162       splitter.split_mask = e->mask();
0163       splitter.width      = e->width();
0164       splitter.offset     = e->offset();
0165       splitter.max_split  = 1 << e->width();
0166     }
0167     else   {
0168       splitter.det_mask |= e->mask();
0169     }
0170     splitter.cell_mask = (splitter.cell_mask << e->width());
0171     printout(INFO,"DigiSegmentationTool",
0172              "%-24s %-8s [%3d,%7d] width:%2d offset:%2d mask:%016lX Split:%016lX Det:%016lX Cells:%016lX",
0173              this->iddescriptor.name(), e->name().c_str(),
0174              e->minValue(), e->maxValue(), e->width(), e->offset(),
0175              e->mask(), splitter.split_mask, splitter.det_mask, splitter.cell_mask);
0176     if ( splitter.field ) break;
0177   }
0178   if ( !splitter.field )   {
0179     except("DigiSegmentationTool",
0180            "FAILED: The ID descriptor for detector %s has no field %s.",
0181            this->detector.name(), split_by.c_str());
0182   }
0183   return splitter;
0184 }
0185 
0186 /// Create full set of detector segments which can be split according to the context
0187 std::set<uint32_t> DigiSegmentationTool::split_segmentation(const std::string& split_by)  const  {
0188   std::map<VolumeID, std::pair<DetElement, VolumeID> > segmentation_splits;
0189   PlacedVolume     place = this->detector.placement();
0190   const auto& ids = place.volIDs();
0191   VolumeID    vid = this->iddescriptor.encode(ids);
0192   VolumeID    msk = this->iddescriptor.get_mask(ids);
0193   const auto* fld = this->iddescriptor.field(split_by);
0194   const char* det = this->detector.name();
0195 
0196   if ( !fld )   {
0197     except("DigiSegmentationTool","Field discriminator %s does not exist in ID descriptor %s",
0198            split_by.c_str(), this->iddescriptor.name());
0199   }
0200   ::scan_detector(*this, split_by, segmentation_splits, this->detector, vid, msk);
0201   std::stringstream str;
0202   std::set<uint32_t> splits;
0203   for( const auto& id : segmentation_splits )  {
0204     auto val = ((id.first&fld->mask())>>fld->offset());
0205     splits.insert(val);
0206   }
0207   for( const auto& id : splits )  {
0208     str << std::setw(16) << std::hex << std::setfill(' ') << id << " ";
0209   }
0210   printout(INFO,"DigiSegmentationTool",
0211            "%-24s has %ld entries and %ld parallel entries when splitting by \"%s\"",
0212            det, segmentation_splits.size(), splits.size(), split_by.c_str());
0213   printout(INFO,"DigiSegmentationTool","%-24s --> %-12s ids: %s",
0214            "", split_by.c_str(), str.str().c_str());
0215   return splits;
0216 }