File indexing completed on 2025-01-18 09:14:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/Printout.h>
0016 #include <DDDigi/DigiData.h>
0017 #include <DDDigi/DigiSegmentationTool.h>
0018
0019
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
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
0057 const char* DigiSegmentContext::cname() const {
0058 return this->field ? this->field->name().c_str() : "";
0059 }
0060
0061
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
0071 DigiSegmentationTool::DigiSegmentationTool(Detector& desc)
0072 : description(desc)
0073 {
0074 }
0075
0076
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
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
0110 std::vector<Key> DigiSegmentationTool::collection_keys() const {
0111 return collection_keys(0x0);
0112 }
0113
0114
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
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
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
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
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 }