File indexing completed on 2025-06-30 07:55:01
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef DD4HEP_DDCMSDETELEMENTCREATOR_H
0018 #define DD4HEP_DDCMSDETELEMENTCREATOR_H
0019
0020
0021 #include "DD4hep/VolumeProcessor.h"
0022
0023 namespace dd4hep {
0024
0025
0026
0027
0028
0029
0030
0031
0032 class DDCMSDetElementCreator : public PlacedVolumeProcessor {
0033 Detector& description;
0034 Atom silicon;
0035 struct Data {
0036 PlacedVolume pv {0};
0037 DetElement element {};
0038 bool sensitive = false;
0039 bool has_sensitive = false;
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
0062 Counters counters;
0063 LeafCount leafCount;
0064 VolumeStack stack;
0065 Detectors subdetectors;
0066 DetElement tracker, current_detector;
0067 SensitiveDetector current_sensitive;
0068 std::map<PlacedVolume, std::pair<int,int> > all_placements;
0069
0070
0071 DetElement addSubdetector(const std::string& nam, PlacedVolume pv, bool volid);
0072
0073 DetElement createElement(const char* debug_tag, PlacedVolume pv, int id);
0074
0075 void createTopLevelDetectors(PlacedVolume pv);
0076
0077 public:
0078
0079 DDCMSDetElementCreator(Detector& desc);
0080
0081 virtual ~DDCMSDetElementCreator();
0082
0083 virtual int operator()(PlacedVolume pv, int level);
0084
0085 virtual int process(PlacedVolume pv, int level, bool recursive);
0086 };
0087 }
0088 #endif
0089
0090 #include "DD4hep/detail/DetectorInterna.h"
0091 #include "DD4hep/DetFactoryHelper.h"
0092 #include "DD4hep/DetectorHelper.h"
0093 #include "DD4hep/Printout.h"
0094 #include "DDCMS/DDCMS.h"
0095
0096 #include <sstream>
0097
0098 using namespace std;
0099 using namespace dd4hep;
0100
0101
0102 DDCMSDetElementCreator::DDCMSDetElementCreator(Detector& desc)
0103 : description(desc)
0104 {
0105 DetectorHelper helper(description);
0106 silicon = helper.element("materials:Silicon");
0107 if ( !silicon.isValid() ) {
0108 except("DDCMSDetElementCreator",
0109 "++ Failed to extract SILICON from the element table.");
0110 }
0111 stack.reserve(32);
0112 }
0113
0114
0115 DDCMSDetElementCreator::~DDCMSDetElementCreator() {
0116 Count total;
0117 stringstream str, id_str;
0118
0119 printout(INFO,"DDCMSDetElementCreator","+++++++++++++++ Summary of sensitve elements ++++++++++++++++++++++++");
0120 for ( const auto& c : counters ) {
0121 printout(INFO,"DDCMSDetElementCreator","++ Summary: SD: %-24s %7d DetElements %7d sensitives out of %7d volumes",
0122 (c.first.name()+string(":")).c_str(), c.second.elements, c.second.sensitives, c.second.volumes);
0123 total.elements += c.second.elements;
0124 total.sensitives += c.second.sensitives;
0125 total.volumes += c.second.volumes;
0126 }
0127 printout(INFO,"DDCMSDetElementCreator", "++ Summary: %-24s %7d DetElements %7d sensitives out of %7d volumes",
0128 "Grand Total:",total.elements,total.sensitives,total.volumes);
0129 printout(INFO,"DDCMSDetElementCreator","+++++++++++++++ Summary of geometry depth analysis ++++++++++++++++++");
0130 int total_cnt = 0;
0131 map<DetElement, vector<pair<int,int> > > fields;
0132 for ( const auto& l : leafCount ) {
0133 DetElement de = l.first.first;
0134 printout(INFO,"DDCMSDetElementCreator","++ Summary: SD: %-24s system:%04X Lvl:%3d Sensitives: %6d [Max: %6d].",
0135 (de.name()+string(":")).c_str(), de.id(),
0136 l.first.second, l.second.second, l.second.first);
0137 fields[de].push_back(make_pair(l.first.second,l.second.first));
0138 ++total_cnt;
0139 }
0140 printout(INFO,"DDCMSDetElementCreator","++ Summary: %-24s %d.","Total DetElements:",total_cnt);
0141 printout(INFO,"DDCMSDetElementCreator","+++++++++++++++ Readout structure generation ++++++++++++++++++++++++");
0142 str << endl;
0143 for( const auto& f : fields ) {
0144 string ro_name = f.first.name() + string("Hits");
0145 int num_bits = 8;
0146 id_str.str("");
0147 id_str << "system:" << num_bits;
0148 for( const auto& q : f.second ) {
0149 int bits = 0;
0150 if ( q.second < 1<<0 ) bits = 1;
0151 else if ( q.second < 1<<1 ) bits = 1;
0152 else if ( q.second < 1<<2 ) bits = 2;
0153 else if ( q.second < 1<<3 ) bits = 3;
0154 else if ( q.second < 1<<4 ) bits = 4;
0155 else if ( q.second < 1<<5 ) bits = 5;
0156 else if ( q.second < 1<<6 ) bits = 6;
0157 else if ( q.second < 1<<7 ) bits = 7;
0158 else if ( q.second < 1<<8 ) bits = 8;
0159 else if ( q.second < 1<<9 ) bits = 9;
0160 else if ( q.second < 1<<10 ) bits = 10;
0161 else if ( q.second < 1<<11 ) bits = 11;
0162 else if ( q.second < 1<<12 ) bits = 12;
0163 else if ( q.second < 1<<13 ) bits = 13;
0164 else if ( q.second < 1<<14 ) bits = 14;
0165 else if ( q.second < 1<<15 ) bits = 15;
0166 bits += 1;
0167 id_str << ",Lv" << q.first << ":" << bits;
0168 num_bits += bits;
0169 }
0170 string idspec = id_str.str();
0171 str << "<readout name=\"" << ro_name << "\">" << endl
0172 << "\t<id>"
0173 << idspec
0174 << "</id> <!-- Number of bits: " << num_bits << " -->" << endl
0175 << "</readout>" << endl;
0176
0177 IDDescriptor dsc(ro_name,idspec);
0178 description.addIDSpecification(dsc);
0179 Readout ro(ro_name);
0180 ro.setIDDescriptor(dsc);
0181 description.addReadout(ro);
0182 SensitiveDetector sd = description.sensitiveDetector(f.first.name());
0183 sd.setHitsCollection(ro.name());
0184 sd.setReadout(ro);
0185 printout(INFO,"DDCMSDetElementCreator",
0186 "++ Setting up readout for subdetector:%-24s id:%04X",
0187 f.first.name(), f.first.id());
0188 }
0189 printout(INFO,"DDCMSDetElementCreator","+++++++++++++++ ID Descriptor generation ++++++++++++++++++++++++++++");
0190 printout(INFO,"",str.str().c_str());
0191 char volid[32];
0192 for(auto& p : all_placements ) {
0193 PlacedVolume place = p.first;
0194 Volume vol = place.volume();
0195 ::snprintf(volid,sizeof(volid),"Lv%d", p.second.first);
0196 printout(DEBUG,"DDCMSDetElementCreator",
0197 "++ Set volid (%-24s): %-6s = %3d -> %s (%p)",
0198 vol.isSensitive() ? vol.sensitiveDetector().name() : "Not Sensitive",
0199 volid, p.second.second, place.name(), place.ptr());
0200 place.addPhysVolID(volid, p.second.second);
0201 }
0202 printout(ALWAYS,"DDCMSDetElementCreator",
0203 "++ Instrumented %ld subdetectors with %d DetElements %d sensitives out of %d volumes and %ld sensitive placements.",
0204 fields.size(),total.elements,total.sensitives,total.volumes,all_placements.size());
0205 }
0206
0207
0208 DetElement DDCMSDetElementCreator::createElement(const char* , PlacedVolume pv, int id) {
0209 string name = cms::detElementName(pv);
0210 DetElement det(name, id);
0211 det.setPlacement(pv);
0212
0213
0214
0215
0216 return det;
0217 }
0218
0219
0220 void DDCMSDetElementCreator::createTopLevelDetectors(PlacedVolume pv) {
0221 auto& data = stack.back();
0222 if ( stack.size() == 2 ) {
0223 data.element = tracker = addSubdetector(cms::detElementName(pv), pv, false);
0224 tracker->SetTitle("compound");
0225 }
0226 else if ( stack.size() == 3 ) {
0227 data.element = current_detector = addSubdetector(cms::detElementName(pv), pv, true);
0228 }
0229 }
0230
0231
0232 DetElement DDCMSDetElementCreator::addSubdetector(const std::string& nam, PlacedVolume pv, bool volid) {
0233 Detectors::iterator idet = subdetectors.find(nam);
0234 if ( idet == subdetectors.end() ) {
0235 DetElement det(nam, subdetectors.size()+1);
0236 det.setPlacement(pv);
0237 if ( volid ) {
0238 det.placement().addPhysVolID("system",det.id());
0239 }
0240 idet = subdetectors.insert(make_pair(nam,det)).first;
0241 description.add(det);
0242 }
0243 return idet->second;
0244 }
0245
0246
0247 int DDCMSDetElementCreator::operator()(PlacedVolume pv, int vol_level) {
0248 double frac_si = pv.volume().material().fraction(silicon);
0249 if ( frac_si > 90e-2 ) {
0250 Data& data = stack.back();
0251 data.sensitive = true;
0252 data.has_sensitive = true;
0253 ++data.vol_count;
0254 int idx = pv->GetMotherVolume()->GetIndex(pv.ptr())+1;
0255 auto& cnt = leafCount[make_pair(current_detector,vol_level)];
0256 cnt.first = std::max(cnt.first,idx);
0257 ++cnt.second;
0258 all_placements[pv] = make_pair(vol_level,idx);
0259 return 1;
0260 }
0261 return 0;
0262 }
0263
0264
0265 int DDCMSDetElementCreator::process(PlacedVolume pv, int level, bool recursive) {
0266 stack.push_back(Data(pv));
0267 if ( stack.size() <= 3 ) {
0268 createTopLevelDetectors(pv);
0269 }
0270 int ret = PlacedVolumeProcessor::process(pv,level,recursive);
0271
0272
0273 if ( stack.size() > 3 ) {
0274
0275
0276 auto& data = stack.back();
0277 auto& parent = stack[stack.size()-2];
0278 auto& counts = counters[current_detector];
0279 if ( data.sensitive ) {
0280
0281 if ( !current_sensitive.isValid() ) {
0282 SensitiveDetector sd = description.sensitiveDetector(current_detector.name());
0283 if ( !sd.isValid() ) {
0284 sd = SensitiveDetector(current_detector.name(),"tracker");
0285 current_detector->flag |= DetElement::Object::HAVE_SENSITIVE_DETECTOR;
0286 description.add(sd);
0287 }
0288 current_sensitive = sd;
0289 }
0290 pv.volume().setSensitiveDetector(current_sensitive);
0291 ++counts.sensitives;
0292 }
0293 ++counts.volumes;
0294 bool added = false;
0295 if ( data.vol_count > 0 ) {
0296 parent.daughter_count += data.vol_count;
0297 parent.daughter_count += data.daughter_count;
0298 data.has_sensitive = true;
0299 }
0300 else {
0301 parent.daughter_count += data.daughter_count;
0302 data.has_sensitive = (data.daughter_count>0);
0303 }
0304
0305 if ( data.has_sensitive ) {
0306
0307
0308 if ( !data.element.isValid() ) {
0309 data.element = createElement("Element", data.pv, current_detector.id());
0310 ++counts.elements;
0311 }
0312 if ( !parent.element.isValid() ) {
0313 parent.element = createElement("Parent ", parent.pv, current_detector.id());
0314 ++counts.elements;
0315 }
0316 printout(DEBUG,"DDCMSDetElementCreator",
0317 "++ Assign detector element: %s (%p, %ld children) to %s (%p) with %ld vols",
0318 data.element.name(), data.element.ptr(), data.element.children().size(),
0319 parent.element.name(), parent.element.ptr(),
0320 data.vol_count);
0321
0322
0323
0324 parent.has_sensitive = true;
0325 parent.element.add(data.element);
0326 added = true;
0327
0328
0329 int vol_level = level;
0330 int idx = data.pv->GetMotherVolume()->GetIndex(data.pv.ptr())+1;
0331 all_placements[data.pv] = make_pair(vol_level,idx);
0332
0333 auto& cnt_det = leafCount[make_pair(current_detector,vol_level)];
0334 cnt_det.first = std::max(cnt_det.first,idx);
0335 cnt_det.second += 1;
0336 }
0337 if ( !added && data.element.isValid() ) {
0338 printout(WARNING,"MEMORY-LEAK","Level:%3d Orpahaned DetElement:%s Daugthers:%d Parent:%s",
0339 int(stack.size()), data.element.name(), data.vol_count, parent.pv.name());
0340 }
0341 }
0342
0343 if ( stack.size() == 3 ) {
0344 current_sensitive = SensitiveDetector();
0345 current_detector = DetElement();
0346 }
0347 stack.pop_back();
0348 return ret;
0349 }
0350
0351 static void* create_object(Detector& description, int , char** ) {
0352 PlacedVolumeProcessor* proc = new DDCMSDetElementCreator(description);
0353 return (void*)proc;
0354 }
0355
0356
0357 DECLARE_DD4HEP_CONSTRUCTOR(DDCMS_DetElementCreator,create_object)
0358