File indexing completed on 2025-01-18 09:13:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef DD4HEP_DETELEMENTCREATOR_H
0018 #define DD4HEP_DETELEMENTCREATOR_H
0019
0020
0021 #include <DD4hep/VolumeProcessor.h>
0022 #include <DD4hep/Printout.h>
0023
0024 namespace dd4hep {
0025
0026
0027
0028
0029
0030
0031
0032
0033 class DetElementCreator : public PlacedVolumeProcessor {
0034 struct Data {
0035 PlacedVolume pv {0};
0036 DetElement element {};
0037 bool sensitive = false;
0038 bool has_sensitive = false;
0039 int level = 0;
0040 int vol_count = 0;
0041 int daughter_count = 0;
0042 int sensitive_count = 0;
0043
0044 Data() = default;
0045 Data(PlacedVolume v) : pv(v) {}
0046 Data(const Data& d) = default;
0047 Data& operator=(const Data& d) = default;
0048 };
0049 struct Count {
0050 int elements = 0;
0051 int volumes = 0;
0052 int sensitives = 0;
0053 Count() = default;
0054 Count(const Count&) = default;
0055 Count& operator=(const Count&) = default;
0056 };
0057 typedef std::vector<Data> VolumeStack;
0058 typedef std::map<std::string,DetElement> Detectors;
0059 typedef std::map<DetElement,Count> Counters;
0060 typedef std::map<std::pair<DetElement,int>, std::pair<int,int> > LeafCount;
0061 typedef std::map<PlacedVolume, std::pair<int,int> > AllPlacements;
0062 Detector& description;
0063 Material sensitive_material;
0064 Counters counters;
0065 LeafCount leafCount;
0066 VolumeStack stack;
0067 Detectors subdetectors;
0068 DetElement current_detector;
0069 std::string detector;
0070 std::string sensitive_material_name;
0071 std::string sensitive_type;
0072 std::string detector_volume_match;
0073 std::string detector_volume_veto;
0074 size_t detector_volume_level = 0;
0075 int max_volume_level = 9999;
0076 PrintLevel printLevel = INFO;
0077 SensitiveDetector current_sensitive;
0078 AllPlacements all_placements;
0079
0080
0081 DetElement addSubdetector(const std::string& nam, PlacedVolume pv, bool volid);
0082
0083 DetElement createElement(const char* debug_tag, PlacedVolume pv, int id);
0084
0085 void createTopLevelDetectors(PlacedVolume pv);
0086
0087 std::string detElementName(PlacedVolume pv) const;
0088 public:
0089
0090 DetElementCreator(Detector& desc,
0091 const std::string& detector,
0092 const std::string& sd_type,
0093 const std::string& sd_match,
0094 const std::string& sd_veto,
0095 const std::string& sd_mat,
0096 int sd_lvl,
0097 PrintLevel p);
0098
0099 virtual ~DetElementCreator() noexcept(false);
0100
0101 virtual int operator()(PlacedVolume pv, int level);
0102
0103 virtual int process(PlacedVolume pv, int level, bool recursive);
0104 };
0105 }
0106 #endif
0107
0108
0109 #include <DD4hep/detail/DetectorInterna.h>
0110 #include <DD4hep/DetFactoryHelper.h>
0111 #include <DD4hep/DetectorHelper.h>
0112 #include <DD4hep/Printout.h>
0113
0114
0115 #include <sstream>
0116
0117 using namespace std;
0118 using namespace dd4hep;
0119
0120
0121 DetElementCreator::DetElementCreator(Detector& desc,
0122 const std::string& det,
0123 const string& sd_match,
0124 const string& sd_veto,
0125 const string& sd_type,
0126 const string& sd_mat, int sd_lvl,
0127 PrintLevel p)
0128 : description(desc), detector(det), sensitive_material_name(sd_mat),
0129 sensitive_type(sd_type), detector_volume_match(sd_match),
0130 detector_volume_veto(sd_veto), max_volume_level(sd_lvl), printLevel(p)
0131 {
0132 DetectorHelper helper(description);
0133 sensitive_material = desc.material(sensitive_material_name);
0134 if ( !sensitive_material.isValid() ) {
0135 except("DetElementCreator",
0136 "++ Failed to extract MATERIAL from the element table.");
0137 }
0138 stack.reserve(32);
0139 detector_volume_level = 0;
0140 }
0141
0142
0143 DetElementCreator::~DetElementCreator() noexcept(false) {
0144 Count total;
0145 stringstream str, id_str;
0146 const char* pref = detector_volume_match.c_str();
0147 printout(INFO,pref,"DetElementCreator: +++++++++++++++ Summary of sensitve elements ++++++++++++++++++++++++");
0148 for ( const auto& c : counters ) {
0149 printout(INFO,pref,"DetElementCreator: ++ Summary: SD: %-24s %7d DetElements %7d sensitives out of %7d volumes",
0150 (c.first.name()+string(":")).c_str(), c.second.elements, c.second.sensitives, c.second.volumes);
0151 total.elements += c.second.elements;
0152 total.sensitives += c.second.sensitives;
0153 total.volumes += c.second.volumes;
0154 }
0155 printout(INFO,pref,"DetElementCreator: ++ Summary: %-24s %7d DetElements %7d sensitives out of %7d volumes",
0156 "Grand Total:",total.elements,total.sensitives,total.volumes);
0157 printout(INFO,pref,"DetElementCreator: +++++++++++++++ Summary of geometry depth analysis ++++++++++++++++++");
0158 int total_cnt = 0, total_depth = 0;
0159 map<DetElement, vector<pair<int,int> > > fields;
0160 for ( const auto& l : leafCount ) {
0161 DetElement de = l.first.first;
0162 printout(INFO,pref,"DetElementCreator: ++ Summary: SD: %-24s system:%04X Lvl:%3d Sensitives: %6d [Max: %6d].",
0163 (de.name()+string(":")).c_str(), de.id(),
0164 l.first.second, l.second.second, l.second.first);
0165 fields[de].emplace_back(l.first.second,l.second.first);
0166 total_depth += l.second.second;
0167 ++total_cnt;
0168 }
0169 printout(INFO,pref,"DetElementCreator: ++ Summary: %-24s %d.","Total DetElements:",total_cnt);
0170 printout(INFO,pref,"DetElementCreator: +++++++++++++++ Readout structure generation ++++++++++++++++++++++++");
0171 str << endl;
0172 for( const auto& f : fields ) {
0173 string ro_name = f.first.name() + string("Hits");
0174 int num_bits = 8;
0175 id_str.str("");
0176 id_str << "system:" << num_bits;
0177 for( const auto& q : f.second ) {
0178 int bits = 0;
0179 if ( q.second < 1<<0 ) bits = 1;
0180 else if ( q.second < 1<<1 ) bits = 1;
0181 else if ( q.second < 1<<2 ) bits = 2;
0182 else if ( q.second < 1<<3 ) bits = 3;
0183 else if ( q.second < 1<<4 ) bits = 4;
0184 else if ( q.second < 1<<5 ) bits = 5;
0185 else if ( q.second < 1<<6 ) bits = 6;
0186 else if ( q.second < 1<<7 ) bits = 7;
0187 else if ( q.second < 1<<8 ) bits = 8;
0188 else if ( q.second < 1<<9 ) bits = 9;
0189 else if ( q.second < 1<<10 ) bits = 10;
0190 else if ( q.second < 1<<11 ) bits = 11;
0191 else if ( q.second < 1<<12 ) bits = 12;
0192 else if ( q.second < 1<<13 ) bits = 13;
0193 else if ( q.second < 1<<14 ) bits = 14;
0194 else if ( q.second < 1<<15 ) bits = 15;
0195 bits += 1;
0196 id_str << ",Lv" << q.first << ":" << bits;
0197 num_bits += bits;
0198 }
0199 string idspec = id_str.str();
0200 str << "<readout name=\"" << ro_name << "\">" << endl
0201 << "\t<id>"
0202 << idspec
0203 << "</id> <!-- Number of bits: " << num_bits << " -->" << endl
0204 << "</readout>" << endl;
0205
0206
0207 try {
0208 IDDescriptor dsc(ro_name,idspec);
0209 description.addIDSpecification(dsc);
0210 Readout ro(ro_name);
0211 ro.setIDDescriptor(dsc);
0212 description.addReadout(ro);
0213 SensitiveDetector sd = description.sensitiveDetector(f.first.name());
0214 sd.setHitsCollection(ro.name());
0215 sd.setReadout(ro);
0216 printout(INFO,pref,"DetElementCreator: ++ Setting up readout for subdetector:%-24s id:%04X",
0217 f.first.name(), f.first.id());
0218 }
0219 catch(std::exception& e) {
0220 printout(ERROR,pref,"DetElementCreator: ++ FAILED to setup readout for subdetector:%-24s id:%04X [%s]",
0221 f.first.name(), f.first.id(), e.what());
0222 }
0223 }
0224 printout(INFO,pref,"DetElementCreator: "
0225 "+++++++++++++++ ID Descriptor generation ++++++++++++++++++++++++++++");
0226 printout(INFO,"",str.str().c_str());
0227 char volid[32];
0228 for(auto& p : all_placements ) {
0229 try {
0230 PlacedVolume place = p.first;
0231 Volume vol = place.volume();
0232 ::snprintf(volid,sizeof(volid),"Lv%d", p.second.first);
0233 printout(DEBUG,pref, "DetElementCreator: ++ Set volid (%-24s): %-6s = %3d -> %s (%p)",
0234 vol.isSensitive() ? vol.sensitiveDetector().name() : "Not Sensitive",
0235 volid, p.second.second, place.name(), place.ptr());
0236 place.addPhysVolID(volid, p.second.second);
0237 }
0238 catch(const exception& e) {
0239 except(pref, "DetElementCreator: Exception on destruction: %s", e.what());
0240 }
0241 catch(...) {
0242 except(pref, "DetElementCreator: UNKNOWN Exception on destruction.");
0243 }
0244 }
0245 printout(ALWAYS, pref, "DetElementCreator: ++ Instrumented %ld subdetectors with %d "
0246 "DetElements %d sensitives out of %d volumes and %ld sensitive placements.",
0247 fields.size(),total.elements,total.sensitives,total.volumes,all_placements.size());
0248 }
0249
0250
0251 string DetElementCreator::detElementName(PlacedVolume pv) const {
0252 if ( pv.isValid() ) {
0253 string nam = pv.name();
0254 size_t idx = string::npos;
0255 string nnam = nam.substr(0, idx);
0256 return nnam;
0257 }
0258 except("DetElementCreator","++ Cannot deduce name from invalid PlacedVolume handle!");
0259 return string();
0260 }
0261
0262
0263 DetElement DetElementCreator::createElement(const char* , PlacedVolume pv, int id) {
0264 string name = detElementName(pv);
0265 DetElement det(name, id);
0266 det.setPlacement(pv);
0267
0268
0269
0270
0271 return det;
0272 }
0273
0274
0275 void DetElementCreator::createTopLevelDetectors(PlacedVolume pv) {
0276 auto& data = stack.back();
0277 data.element = current_detector = addSubdetector(detElementName(pv), pv, true);
0278 }
0279
0280
0281 DetElement DetElementCreator::addSubdetector(const std::string& nam, PlacedVolume pv, bool volid) {
0282 Detectors::iterator idet = subdetectors.find(nam);
0283 if ( idet == subdetectors.end() ) {
0284 DetElement det(nam, description.detectors().size()+1);
0285 det.setPlacement(pv);
0286 if ( volid ) {
0287 det.placement().addPhysVolID("system",det.id());
0288 }
0289 idet = subdetectors.emplace(nam,det).first;
0290 description.add(det);
0291 printout(printLevel,"DetElementCreator","++ Added sub-detector element: %s",det.path().c_str());
0292 }
0293 return idet->second;
0294 }
0295
0296
0297 int DetElementCreator::operator()(PlacedVolume pv, int vol_level) {
0298 if ( detector_volume_level > 0 ) {
0299 Material mat = pv.volume().material();
0300 if ( mat == sensitive_material ) {
0301 Data& data = stack.back();
0302 data.sensitive = true;
0303 data.has_sensitive = true;
0304 ++data.vol_count;
0305 int idx = pv->GetMotherVolume()->GetIndex(pv.ptr())+1;
0306 auto& cnt = leafCount[make_pair(current_detector,vol_level)];
0307 cnt.first = std::max(cnt.first,idx);
0308 ++cnt.second;
0309 all_placements[pv] = make_pair(vol_level,idx);
0310 return 1;
0311 }
0312 }
0313 return 0;
0314 }
0315
0316
0317 int DetElementCreator::process(PlacedVolume pv, int lvl, bool recursive) {
0318 int ret = 1;
0319 string pv_nam = pv.name();
0320 if ( detector_volume_level > 0 ||
0321 ( (!detector_volume_match.empty() &&
0322 pv_nam.find(detector_volume_match) != string::npos) &&
0323 (detector_volume_veto.empty() ||
0324 pv_nam.find(detector_volume_veto) == string::npos) ) )
0325 {
0326 stack.emplace_back(Data(pv));
0327 if ( 0 == detector_volume_level ) {
0328 detector_volume_level = stack.size();
0329 createTopLevelDetectors(pv);
0330 }
0331 ret = PlacedVolumeProcessor::process(pv,lvl,recursive);
0332
0333 if ( stack.size() > detector_volume_level ) {
0334
0335
0336 auto& data = stack.back();
0337 auto& parent = stack[stack.size()-2];
0338 auto& counts = counters[current_detector];
0339 if ( data.sensitive ) {
0340
0341 if ( !current_sensitive.isValid() ) {
0342 SensitiveDetector sd = description.sensitiveDetector(current_detector.name());
0343 if ( !sd.isValid() ) {
0344 sd = SensitiveDetector(current_detector.name(), sensitive_type);
0345 current_detector->flag |= DetElement::Object::HAVE_SENSITIVE_DETECTOR;
0346 description.add(sd);
0347
0348 }
0349 current_sensitive = sd;
0350 }
0351 pv.volume().setSensitiveDetector(current_sensitive);
0352 ++counts.sensitives;
0353 }
0354 ++counts.volumes;
0355 bool added = false;
0356 if ( data.vol_count > 0 ) {
0357 parent.daughter_count += data.vol_count;
0358 parent.daughter_count += data.daughter_count;
0359 data.has_sensitive = true;
0360 }
0361 else {
0362 parent.daughter_count += data.daughter_count;
0363 data.has_sensitive = (data.daughter_count>0);
0364 }
0365
0366 if ( data.has_sensitive ) {
0367
0368
0369 if ( data.pv.volIDs().empty() ) {
0370 char text[32];
0371 ::snprintf(text, sizeof(text), "Lv%d", lvl);
0372 data.pv.addPhysVolID(text, data.pv->GetMotherVolume()->GetIndex(data.pv.ptr())+1);
0373 }
0374 else {
0375 AllPlacements::const_iterator e = all_placements.find(data.pv);
0376 if ( e != all_placements.end() && (*e).second.first != lvl) {
0377 printout(ERROR,"DetElementCreator","PLacement VOLID error: %d <> %d",lvl,(*e).second.first);
0378 }
0379 }
0380
0381 for(size_t i=1; i<stack.size(); ++i) {
0382 auto& d = stack[i];
0383 auto& p = stack[i-1];
0384 if ( !d.element.isValid() ) {
0385 d.element = createElement("Element", d.pv, current_detector.id());
0386 (i==1 ? current_detector : p.element).add(d.element);
0387 ++counts.elements;
0388 }
0389 p.has_sensitive = true;
0390 }
0391 printout(printLevel,"DetElementCreator",
0392 "++ Assign detector element: %s (%p, %ld children) to %s (%p) with %ld vols",
0393 data.element.name(), data.element.ptr(), data.element.children().size(),
0394 parent.element.name(), parent.element.ptr(), data.vol_count);
0395 added = true;
0396
0397
0398 int vol_level = lvl;
0399 int idx = data.pv->GetMotherVolume()->GetIndex(data.pv.ptr())+1;
0400 all_placements[data.pv] = make_pair(vol_level,idx);
0401
0402 auto& cnt_det = leafCount[make_pair(current_detector,vol_level)];
0403 cnt_det.first = std::max(cnt_det.first,idx);
0404 cnt_det.second += 1;
0405 printout(printLevel,"DetElementCreator","++ [%ld] Added element: %s",
0406 stack.size(), data.element.path().c_str());
0407 }
0408 if ( !added && data.element.isValid() ) {
0409 printout(WARNING,"MEMORY-LEAK","Level:%3d Orpahaned DetElement:%s Daugthers:%d Parent:%s",
0410 int(stack.size()), data.element.name(), data.vol_count, parent.pv.name());
0411 }
0412 }
0413
0414 if ( stack.size() == detector_volume_level ) {
0415 current_sensitive = SensitiveDetector();
0416 current_detector = DetElement();
0417 detector_volume_level = 0;
0418 ret = 0;
0419 }
0420 stack.pop_back();
0421 }
0422 else if ( lvl < max_volume_level ) {
0423
0424 ret = PlacedVolumeProcessor::process(pv,lvl,recursive);
0425 }
0426 return ret;
0427 }
0428
0429 static void* create_object(Detector& description, int argc, char** argv) {
0430 PrintLevel prt = DEBUG;
0431 size_t sd_level = 99999;
0432 string sd_mat, sd_match, sd_veto, sd_type, detector;
0433 for(int i = 0; i < argc && argv[i]; ++i) {
0434 if ( 0 == ::strncmp("-material",argv[i],5) )
0435 sd_mat = argv[++i];
0436 else if ( 0 == ::strncmp("-match",argv[i],5) )
0437 sd_match = argv[++i];
0438 else if ( 0 == ::strncmp("-detector",argv[i],5) )
0439 detector = argv[++i];
0440 else if ( 0 == ::strncmp("-veto",argv[i],5) )
0441 sd_veto = argv[++i];
0442 else if ( 0 == ::strncmp("-type",argv[i],5) )
0443 sd_type = argv[++i];
0444 else if ( 0 == ::strncmp("-level",argv[i],5) )
0445 sd_level = ::atol(argv[++i]);
0446 else if ( 0 == ::strncmp("-print",argv[i],5) )
0447 prt = decodePrintLevel(argv[++i]);
0448 else
0449 break;
0450 }
0451 if ( sd_mat.empty() || sd_match.empty() || sd_type.empty() ) {
0452 cout <<
0453 "Usage: -plugin <name> -arg [-arg] \n"
0454 " name: factory name DD4hep_ROOTGDMLParse \n"
0455 " -material <string> Sensitive material name (identifier) \n"
0456 " -match <string> Matching string for subdetector identification \n"
0457 "\tArguments given: " << arguments(argc,argv) << endl << flush;
0458 ::exit(EINVAL);
0459 }
0460 PlacedVolumeProcessor* proc = new DetElementCreator(description, detector, sd_match, sd_veto, sd_type, sd_mat, sd_level, prt);
0461 return (void*)proc;
0462 }
0463
0464
0465 DECLARE_DD4HEP_CONSTRUCTOR(DD4hep_DetElementCreator,create_object)
0466