File indexing completed on 2025-01-18 09:14:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DDDigi/noise/DigiSubdetectorSequence.h>
0016 #include <DDDigi/DigiSegmentation.h>
0017 #include <DDDigi/DigiKernel.h>
0018 #include <DDDigi/DigiContext.h>
0019 #include <DDDigi/DigiData.h>
0020
0021 #include <DD4hep/InstanceCount.h>
0022 #include <DD4hep/Detector.h>
0023 #include <DD4hep/IDDescriptor.h>
0024 #include <DD4hep/detail/VolumeManagerInterna.h>
0025 #include <TClass.h>
0026
0027
0028 #include <stdexcept>
0029
0030 using namespace dd4hep::digi;
0031
0032
0033 DigiSubdetectorSequence::DigiSubdetectorSequence(const DigiKernel& kernel, const std::string& nam)
0034 : DigiActionSequence(kernel, nam)
0035 {
0036 declareProperty("detector",m_detectorName);
0037 declareProperty("parallize_by",m_segmentName);
0038 m_cellHandler = [this](DigiContext& context, const DigiCellScanner& scanner, const DigiCellData& data) {
0039 this->process_cell(context, scanner, data);
0040 };
0041 InstanceCount::increment(this);
0042 }
0043
0044
0045 DigiSubdetectorSequence::~DigiSubdetectorSequence() {
0046 InstanceCount::decrement(this);
0047 }
0048
0049
0050 void DigiSubdetectorSequence::initialize() {
0051 info("Initializing detector sequencer for detector: %s",m_detectorName.c_str());
0052 m_detector = subdetector(m_detectorName);
0053 m_sensDet = sensitiveDetector(m_detectorName);
0054 m_parallelVid.clear();
0055 m_parallelDet.clear();
0056 if ( m_detector.isValid() && m_sensDet.isValid() ) {
0057 m_idDesc = m_sensDet.readout().idSpec();
0058 m_segmentation = m_sensDet.readout().segmentation();
0059 PlacedVolume plc = m_detector.placement();
0060 const VolIDs& ids = plc.volIDs();
0061 VolumeID vid = m_idDesc.encode(ids);
0062 VolumeID msk = m_idDesc.get_mask(ids);
0063 scan_detector(m_detector, vid, msk);
0064 }
0065 }
0066
0067 void DigiSubdetectorSequence::scan_sensitive(PlacedVolume pv, VolumeID vid, VolumeID mask) {
0068 Volume vol = pv.volume();
0069 if ( vol.isSensitive() ) {
0070 Solid sol = vol.solid();
0071 auto key = std::make_pair(sol->IsA(), m_segmentation);
0072 auto is = m_scanners.find(key);
0073 if ( is == m_scanners.end() ) {
0074 is = m_scanners.insert(std::make_pair(key, create_cell_scanner(sol, m_segmentation))).first;
0075 }
0076 }
0077 for ( int idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau ) {
0078 PlacedVolume p(pv->GetDaughter(idau));
0079 const VolIDs& new_ids = p.volIDs();
0080 if ( !new_ids.empty() ) {
0081 VolumeID new_vid = vid | m_idDesc.encode(new_ids);
0082 VolumeID new_msk = mask | m_idDesc.get_mask(new_ids);
0083 scan_sensitive(p, new_vid, new_msk);
0084 continue;
0085 }
0086 scan_sensitive(p, vid, mask);
0087 }
0088 }
0089
0090 void DigiSubdetectorSequence::scan_detector(DetElement de, VolumeID vid, VolumeID mask) {
0091 PlacedVolume place = m_detector.placement();
0092 const VolIDs& new_ids = place.volIDs();
0093 VolumeID new_vid = vid;
0094 VolumeID new_msk = mask;
0095 if ( !new_ids.empty() ) {
0096 new_vid |= m_idDesc.encode(new_ids);
0097 new_msk |= m_idDesc.get_mask(new_ids);
0098 for (const auto& id : new_ids) {
0099 if ( id.first == m_segmentName ) {
0100 VolumeID rid = detail::reverseBits<VolumeID>(new_vid);
0101 m_parallelVid.emplace(std::make_pair(rid, Context(de, new_vid, rid, new_msk)));
0102 m_parallelDet.emplace(std::make_pair(de, new_vid));
0103 scan_sensitive(de.placement(), new_vid, new_msk);
0104 return;
0105 }
0106 }
0107 }
0108 for ( const auto& c : de.children() )
0109 scan_detector(c.second, new_vid, new_msk);
0110 }
0111
0112
0113 void DigiSubdetectorSequence::process_cell(DigiContext&, const DigiCellScanner& , const DigiCellData& ) const {
0114 #if 0
0115 Segmentation seg = m_sensDet.readout().segmentation();
0116 std::string desc = m_idDesc.str(data.cell_id);
0117 info("Sensitive: [%s/%s] vid:%s %s",
0118 data.solid->IsA()->GetName(),
0119 seg.type().c_str(),
0120 volumeID(data.cell_id).c_str(),
0121 desc.c_str());
0122 if ( data.cell_id ) {
0123 }
0124 #endif
0125 }
0126
0127 void DigiSubdetectorSequence::process_context(DigiContext& context,
0128 const Context& c,
0129 PlacedVolume pv,
0130 VolumeID vid,
0131 VolumeID mask) const
0132 {
0133 Volume vol = pv.volume();
0134 if ( vol.isSensitive() ) {
0135 auto key = std::make_pair(vol->GetShape()->IsA(), m_segmentation);
0136 auto is = m_scanners.find(key);
0137 if ( is == m_scanners.end() ) {
0138 except("Fatal error in process_context: Invalid cell scanner. vid: %016X",vid);
0139 }
0140 (*(is->second))(context, pv, vid, m_cellHandler);
0141 return;
0142 }
0143 for (int idau = 0, ndau = pv->GetNdaughters(); idau < ndau; ++idau) {
0144 PlacedVolume p(pv->GetDaughter(idau));
0145 const VolIDs& new_ids = p.volIDs();
0146 if ( !new_ids.empty() )
0147 process_context(context, c, p, vid | m_idDesc.encode(new_ids), mask | m_idDesc.get_mask(new_ids));
0148 else
0149 process_context(context, c, p, vid, mask);
0150 }
0151 }
0152
0153
0154 void DigiSubdetectorSequence::execute(DigiContext& context) const {
0155 for( const auto& d : m_parallelVid ) {
0156 const Context& c = d.second;
0157 auto vid = c.detector_id;
0158 auto det = c.detector;
0159 std::string id_desc = m_idDesc.str(vid);
0160 info(" Order:%-64s vid:%s %s %s",
0161 det.path().c_str(), volumeID(d.first).c_str(), volumeID(vid).c_str(), id_desc.c_str());
0162 process_context(context, c, c.detector.placement(), c.detector_id, c.detector_mask);
0163 }
0164 this->DigiSynchronize::execute(context);
0165 debug("+++ Event: %8d (DigiSubdetectorSequence) Parallel: %s Done.",
0166 context.event->eventNumber, yes_no(m_parallel));
0167 }
0168
0169
0170 dd4hep::DetElement DigiSubdetectorSequence::subdetector(const std::string& nam) const {
0171 return m_kernel.detectorDescription().detector(nam);
0172 }
0173
0174
0175 dd4hep::SensitiveDetector DigiSubdetectorSequence::sensitiveDetector(const std::string& nam) const {
0176 return m_kernel.detectorDescription().sensitiveDetector(nam);
0177 }