File indexing completed on 2025-01-18 09:14:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <DD4hep/Printout.h>
0016 #include <DD4hep/Primitives.h>
0017 #include <DD4hep/InstanceCount.h>
0018 #define G__ROOT
0019 #include <DDDigi/DigiData.h>
0020
0021
0022 #include <mutex>
0023
0024 namespace {
0025 struct digi_keys {
0026 std::mutex lock;
0027 std::map<unsigned long, std::string> map;
0028 };
0029 digi_keys& keys() {
0030 static digi_keys k;
0031 return k;
0032 }
0033 }
0034
0035 using namespace dd4hep::digi;
0036
0037 std::string dd4hep::digi::digiTypeName(const std::type_info& info) {
0038 using detail::str_replace;
0039 std::string typ = typeName(info);
0040 std::size_t idx = typ.find(", std::allocator<std::");
0041 if ( idx != std::string::npos ) typ = str_replace(typ, typ.substr(idx), ">");
0042 typ = str_replace(str_replace(typ,"std::",""),"dd4hep::","");
0043 typ = str_replace(str_replace(typ,"sim::",""),"digi::","");
0044 typ = str_replace(str_replace(typ,", less<Key>",""),", less<long long>","");
0045 return typ;
0046 }
0047
0048 std::string dd4hep::digi::digiTypeName(const std::any& data) {
0049 return digiTypeName(data.type());
0050 }
0051
0052 Key& Key::set(const std::string& name, int mask) {
0053 return this->set(name, 0x0, mask);
0054 }
0055
0056
0057 Key& Key::set(const std::string& name, int segment, int mask) {
0058 auto& _k = keys();
0059 if ( name.empty() ) {
0060 std::lock_guard<std::mutex> lock(_k.lock);
0061 except("DDDigi::Key", "+++ No key name was specified -- this is illegal!");
0062 }
0063 this->key = 0;
0064 this->set_item(detail::hash32(name));
0065 this->set_mask(Key::mask_type(0xFFFF&mask));
0066 this->set_segment(Key::segment_type(0xFF&segment));
0067 std::lock_guard<std::mutex> lock(_k.lock);
0068 _k.map[this->item()] = name;
0069 return *this;
0070 }
0071
0072
0073 Key& Key::set_submask(const char* opt_tag) {
0074 submask_type sm = detail::hash16(opt_tag);
0075 this->values.submask = sm;
0076 return *this;
0077 }
0078
0079
0080 std::string Key::key_name(const Key& k) {
0081 auto& _k = keys();
0082 std::lock_guard<std::mutex> lock(_k.lock);
0083 std::map<unsigned long, std::string>::const_iterator it = _k.map.find(k.item());
0084 if ( it != _k.map.end() ) return it->second;
0085 for( const auto& e : _k.map ) {
0086 if ( e.first == k.values.item )
0087 return e.second;
0088 }
0089 return "UNKNOWN";
0090 }
0091
0092 const Particle& dd4hep::digi::get_history_particle(const DigiEvent& event, Key history_key) {
0093 static Key item_key("MCParticles",0x0);
0094 Key key;
0095 const auto& segment = event.get_segment(history_key.segment());
0096 key.set_segment(history_key.segment());
0097 key.set_mask(history_key.mask());
0098 key.set_item(item_key.item());
0099 const auto& particles = segment.get<ParticleMapping>(std::move(key));
0100 return particles.get(std::move(history_key));
0101 }
0102
0103 const EnergyDeposit& dd4hep::digi::get_history_deposit(const DigiEvent& event, Key::itemkey_type container_item, Key history_key) {
0104 Key key;
0105 const auto& segment = event.get_segment(history_key.segment());
0106 key.set_segment(history_key.segment());
0107 key.set_item(container_item);
0108 key.set_mask(history_key.mask());
0109 const auto& hits = segment.get<DepositVector>(std::move(key));
0110 return hits.at(history_key.item());
0111 }
0112
0113
0114 void History::update(const History& upda) {
0115 hits.insert(hits.end(), upda.hits.begin(), upda.hits.end());
0116 particles.insert(particles.end(), upda.particles.begin(), upda.particles.end());
0117 }
0118
0119
0120 std::pair<std::size_t,std::size_t> History::drop() {
0121 std::pair<std::size_t,std::size_t> ret(hits.size(), particles.size());
0122 hits.clear();
0123 particles.clear();
0124 return ret;
0125 }
0126
0127 const Particle& History::hist_entry_t::get_particle(const DigiEvent& event) const {
0128 static Key item_key("MCParticles",0x0);
0129 Key key(this->source);
0130 const auto& segment = event.get_segment(Key(this->source).segment());
0131 const auto& particle_data = segment.get<ParticleMapping>(key.set_item(item_key.item()));
0132 return particle_data.get(this->source);
0133 }
0134
0135 const EnergyDeposit& History::hist_entry_t::get_deposit(const DigiEvent& event, Key::itemkey_type container_item) const {
0136 Key key(this->source);
0137 const auto& segment = event.get_segment(Key(this->source).segment());
0138 const auto& hit_data = segment.get<DepositVector>(key.set_item(container_item));
0139 return hit_data.at(Key(this->source).item());
0140 }
0141
0142
0143 Direction History::average_particle_momentum(const DigiEvent& event) const {
0144 Direction momentum;
0145 if ( !particles.empty() ) {
0146 double weight = 0e0;
0147 for( const auto& p : particles ) {
0148 const Particle& par = p.get_particle(event);
0149 momentum += par.momentum * p.weight;
0150 weight += p.weight;
0151 }
0152 momentum /= std::max(weight, detail::numeric_epsilon);
0153 }
0154 return momentum;
0155 }
0156
0157
0158 void EnergyDeposit::update_deposit_weighted(const EnergyDeposit& upda) {
0159 double sum = deposit + upda.deposit;
0160 double err = depositError + upda.depositError;
0161 Position pos = ((deposit / sum) * position) + ((upda.deposit / sum) * upda.position);
0162 Direction mom = ((deposit / sum) * momentum) + ((upda.deposit / sum) * upda.momentum);
0163 position = std::move(pos);
0164 momentum = std::move(mom);
0165 deposit = sum;
0166 depositError = err;
0167 history.update(upda.history);
0168 }
0169
0170
0171 void EnergyDeposit::update_deposit_weighted(EnergyDeposit&& upda) {
0172 double sum = deposit + upda.deposit;
0173 double err = depositError + upda.depositError;
0174 Position pos = ((deposit / sum) * position) + ((upda.deposit / sum) * upda.position);
0175 Direction mom = ((deposit / sum) * momentum) + ((upda.deposit / sum) * upda.momentum);
0176 position = std::move(pos);
0177 momentum = std::move(mom);
0178 deposit = sum;
0179 depositError = err;
0180 history.update(std::move(upda.history));
0181 }
0182
0183
0184 std::size_t DepositVector::merge(DepositVector&& updates) {
0185 std::size_t update_size = updates.size();
0186 std::size_t newlen = std::max(2*data.size(), data.size()+updates.size());
0187 data.reserve(newlen);
0188 for( auto& c : updates ) {
0189 data.emplace_back(c);
0190 }
0191 return update_size;
0192 }
0193
0194
0195 std::size_t DepositVector::merge(DepositMapping&& updates) {
0196 std::size_t update_size = updates.size();
0197 std::size_t newlen = std::max(2*data.size(), data.size()+updates.size());
0198 data.reserve(newlen);
0199 for( const auto& c : updates ) {
0200 data.emplace_back(c);
0201 }
0202 return update_size;
0203 }
0204
0205
0206 std::size_t DepositVector::insert(const DepositVector& updates) {
0207 std::size_t update_size = updates.size();
0208 std::size_t newlen = std::max(2*data.size(), data.size()+updates.size());
0209 data.reserve(newlen);
0210 for( const auto& c : updates ) {
0211 data.emplace_back(c);
0212 }
0213 return update_size;
0214 }
0215
0216
0217 std::size_t DepositVector::insert(const DepositMapping& updates) {
0218 std::size_t update_size = updates.size();
0219 std::size_t newlen = std::max(2*data.size(), data.size()+updates.size());
0220 data.reserve(newlen);
0221 for( const auto& c : updates ) {
0222 data.emplace_back(c);
0223 }
0224 return update_size;
0225 }
0226
0227
0228 const EnergyDeposit& DepositVector::get(CellID cell) const {
0229 for( const auto& c : data ) {
0230 if ( c.first == cell ) {
0231 return c.second;
0232 }
0233 }
0234 except("DepositVector","Failed to access deposit by CellID. UNKNOWN ID: %016X", cell);
0235 throw std::runtime_error("Attempt to access non-existing CellID");
0236 }
0237
0238
0239 const EnergyDeposit& DepositVector::at(std::size_t cell) const {
0240 return data.at(cell).second;
0241 }
0242
0243
0244 void DepositVector::remove(iterator ) {
0245
0246 }
0247
0248
0249 std::size_t DepositMapping::merge(DepositVector&& updates) {
0250 std::size_t update_size = updates.size();
0251 for( auto& dep : updates ) {
0252 EnergyDeposit& depo = dep.second;
0253 CellID cell = dep.first;
0254 auto iter = data.find(cell);
0255 if ( iter == data.end() )
0256 data.emplace(dep.first, std::move(depo));
0257 else
0258 iter->second.update_deposit_weighted(std::move(depo));
0259 }
0260 return update_size;
0261 }
0262
0263
0264 std::size_t DepositMapping::merge(DepositMapping&& updates) {
0265 std::size_t update_size = updates.size();
0266 for( auto& dep : updates ) {
0267 const EnergyDeposit& depo = dep.second;
0268 CellID cell = dep.first;
0269 auto iter = data.find(cell);
0270 if ( iter == data.end() )
0271 data.emplace(dep.first, std::move(depo));
0272 else
0273 iter->second.update_deposit_weighted(std::move(depo));
0274 }
0275 return update_size;
0276 }
0277
0278
0279 std::size_t DepositMapping::insert(const DepositVector& updates) {
0280 std::size_t update_size = updates.size();
0281 for( const auto& c : updates ) {
0282 data.emplace(c);
0283 }
0284 return update_size;
0285 }
0286
0287
0288 std::size_t DepositMapping::insert(const DepositMapping& updates) {
0289 std::size_t update_size = updates.size();
0290 for( const auto& c : updates ) {
0291 data.emplace(c);
0292 }
0293 return update_size;
0294 }
0295
0296
0297 void DepositMapping::emplace(CellID cell, EnergyDeposit&& deposit) {
0298 data.emplace(cell, std::move(deposit));
0299 }
0300
0301
0302 const EnergyDeposit& DepositMapping::get(CellID cell) const {
0303 auto iter = data.find(cell);
0304 if ( iter != data.end() )
0305 return iter->second;
0306 except("DepositMapping","Failed to access deposit by CellID. UNKNOWN ID: %016X", cell);
0307 throw std::runtime_error("Failed to access deposit by CellID");
0308 }
0309
0310
0311 void DepositMapping::remove(iterator position) {
0312 data.erase(position);
0313 }
0314
0315
0316 void Particle::move_position(const Position& delta) {
0317 this->start_position += delta;
0318 this->end_position += delta;
0319 }
0320
0321
0322 std::size_t ParticleMapping::insert(const ParticleMapping& updates) {
0323 std::size_t update_size = updates.size();
0324 for( const ParticleMapping::value_type& c : updates )
0325 this->insert(c.first, c.second);
0326 return update_size;
0327 }
0328
0329
0330 std::size_t ParticleMapping::merge(ParticleMapping&& updates) {
0331 std::size_t update_size = updates.size();
0332 for( ParticleMapping::value_type& c : updates ) {
0333 Particle part(std::move(c.second));
0334 this->push(Key(c.first), std::move(part));
0335 }
0336 return update_size;
0337 }
0338
0339 void ParticleMapping::push(Key particle_key, Particle&& particle_data) {
0340 bool ret = data.emplace(particle_key, std::move(particle_data)).second;
0341 if ( !ret ) {
0342 except("ParticleMapping","Error in particle map. Duplicate ID: mask:%04X Number:%d History:%s",
0343 particle_key.mask(), particle_key.item(), yes_no(1));
0344 }
0345 }
0346
0347 void ParticleMapping::insert(Key particle_key, const Particle& particle_data) {
0348 bool ret = data.emplace(particle_key, particle_data).second;
0349 if ( !ret ) {
0350 except("ParticleMapping","Error in particle map. Duplicate ID: mask:%04X Number:%d History:%s",
0351 particle_key.mask(), particle_key.item(), yes_no(1));
0352 }
0353 }
0354
0355
0356 void ParticleMapping::emplace(Key particle_key, Particle&& particle_data) {
0357 data.emplace(particle_key, std::move(particle_data));
0358 }
0359
0360
0361 const Particle& ParticleMapping::get(Key particle_key) const {
0362 auto iter = data.find(particle_key);
0363 if ( iter != data.end() )
0364 return iter->second;
0365 except("ParticleMapping","Error in particle map. UNKNOWN ID: %016X segment:%04X mask:%04X Number:%d",
0366 particle_key.value(), particle_key.segment(), particle_key.mask(), particle_key.item());
0367 return iter->second;
0368 }
0369
0370
0371 std::size_t DetectorResponse::merge(DetectorResponse&& updates) {
0372 std::size_t len = updates.size();
0373 data.insert(data.end(), updates.data.begin(), updates.data.end());
0374 return len;
0375 }
0376
0377
0378 std::size_t DetectorResponse::insert(const DetectorResponse& updates) {
0379 std::size_t len = updates.size();
0380 data.insert(data.end(), updates.data.begin(), updates.data.end());
0381 return len;
0382 }
0383
0384
0385 std::size_t DetectorHistory::merge(DetectorHistory&& updates) {
0386 std::size_t len = updates.size();
0387 if ( data.empty() ) {
0388 data = std::move(updates.data);
0389 }
0390 else {
0391 for(auto& e : updates.data)
0392 data.emplace(data.end(), std::move(e));
0393 }
0394 return len;
0395 }
0396
0397
0398 std::size_t DetectorHistory::insert(const DetectorHistory& updates) {
0399 std::size_t len = updates.size();
0400 data.insert(data.end(), updates.data.begin(), updates.data.end());
0401 return len;
0402 }
0403
0404
0405 DataSegment::DataSegment(std::mutex& l, Key::segment_type i)
0406 : data(), lock(l), id(i)
0407 {
0408 }
0409
0410
0411 bool DataSegment::emplace_any(Key key, std::any&& item) {
0412 bool has_value = item.has_value();
0413 #if DD4HEP_DDDIGI_DEBUG
0414 printout(INFO, "DataSegment", "PUT Key No.%4d: %-32s %016lX -> %04X %04X %08Xld Value:%s %s",
0415 data.size(), Key::key_name(key).c_str(), key.value(), key.segment(), key.mask(), key.item(),
0416 yes_no(has_value), digiTypeName(item.type()).c_str());
0417 #endif
0418 std::lock_guard<std::mutex> l(lock);
0419 bool ret = data.emplace(key, std::move(item)).second;
0420 if ( !ret ) {
0421 except("DataSegment","Error in DataSegment map. Duplicate ID: segment:%04X mask:%04X Number:%d Value:%s",
0422 key.mask(), key.item(), yes_no(has_value));
0423 }
0424 return ret;
0425 }
0426
0427
0428 std::size_t DataParameters::size() const {
0429 return data->stringParams.size()+data->floatParams.size()+data->intParams.size();
0430 }
0431
0432 template bool DataSegment::put(Key key, DataParameters&& data);
0433 template bool DataSegment::put(Key key, DepositVector&& data);
0434 template bool DataSegment::put(Key key, DepositMapping&& data);
0435 template bool DataSegment::put(Key key, ParticleMapping&& data);
0436 template bool DataSegment::put(Key key, DetectorHistory&& data);
0437 template bool DataSegment::put(Key key, DetectorResponse&& data);
0438
0439
0440 bool DataSegment::erase(Key key) {
0441 std::lock_guard<std::mutex> l(lock);
0442 auto iter = data.find(key);
0443 if ( iter != data.end() ) {
0444 data.erase(iter);
0445 return true;
0446 }
0447 return false;
0448 }
0449
0450
0451 std::size_t DataSegment::erase(const std::vector<Key>& keys) {
0452 std::size_t count = 0;
0453 std::lock_guard<std::mutex> l(lock);
0454 for(const auto& key : keys) {
0455 auto iter = data.find(key);
0456 if ( iter != data.end() ) {
0457 data.erase(iter);
0458 ++count;
0459 }
0460 }
0461 return count;
0462 }
0463
0464
0465 void DataSegment::print_keys() const {
0466 size_t count = 0;
0467 for( const auto& e : this->data ) {
0468 Key key(e.first);
0469 printout(INFO, "DataSegment", "Key No.%4d: %-32s %016lX -> %04X %04X %08Xld %s",
0470 count, Key::key_name(key).c_str(), key.value(), key.segment(), key.mask(), key.item(),
0471 digiTypeName(e.second.type()).c_str());
0472 ++count;
0473 }
0474 }
0475
0476
0477 std::string DataSegment::invalid_cast(Key key, const std::type_info& type) const {
0478 return dd4hep::format(0, "Invalid segment data cast. Key:%-32s %016lX -> %04X %04X %08X type:%s",
0479 Key::key_name(key).c_str(), key.value(),
0480 key.segment(), key.mask(), key.item(),
0481 typeName(type).c_str());
0482 }
0483
0484
0485 std::string DataSegment::invalid_request(Key key) const {
0486 return dd4hep::format(0, "Invalid segment data requested. Key:%ld",key.value());
0487 }
0488
0489
0490 std::any* DataSegment::get_item(Key key, bool exc) {
0491 auto it = this->data.find(key);
0492 if (it != this->data.end()) return &it->second;
0493 key.set_segment(0x0);
0494 it = this->data.find(key);
0495 if (it != this->data.end()) return &it->second;
0496
0497 if ( exc ) throw std::runtime_error(invalid_request(std::move(key)));
0498 return nullptr;
0499 }
0500
0501
0502 const std::any* DataSegment::get_item(Key key, bool exc) const {
0503 auto it = this->data.find(key);
0504 if (it != this->data.end()) return &it->second;
0505 key.set_segment(0x0);
0506 it = this->data.find(key);
0507 if (it != this->data.end()) return &it->second;
0508
0509 if ( exc ) throw std::runtime_error(invalid_request(std::move(key)));
0510 return nullptr;
0511 }
0512
0513
0514 DigiEvent::DigiEvent()
0515 {
0516 InstanceCount::increment(this);
0517 }
0518
0519
0520 DigiEvent::DigiEvent(int ev_num) : eventNumber(ev_num)
0521 {
0522 char text[32];
0523 ::snprintf(text, sizeof(text), "Ev:%06d ", ev_num);
0524 m_id = text;
0525 InstanceCount::increment(this);
0526 }
0527
0528
0529 DigiEvent::~DigiEvent()
0530 {
0531 InstanceCount::decrement(this);
0532 }
0533
0534 DataSegment& DigiEvent::access_segment(std::unique_ptr<DataSegment>& segment, Key::segment_type id) {
0535 if ( segment ) {
0536 return *segment;
0537 }
0538 std::lock_guard<std::mutex> guard(m_lock);
0539
0540 if ( !segment ) {
0541 segment = std::make_unique<DataSegment>(this->m_lock, id);
0542 }
0543 return *segment;
0544 }
0545
0546
0547 DataSegment& DigiEvent::get_segment(const std::string& name) {
0548 switch(::toupper(name[0])) {
0549 case 'I':
0550 return access_segment(m_inputs,1);
0551 case 'C':
0552 return access_segment(m_counts,2);
0553 case 'D':
0554 switch(::toupper(name[1])) {
0555 case 'E':
0556 return access_segment(m_deposits,3);
0557 default:
0558 return access_segment(m_data,0xAB);
0559 }
0560 break;
0561 case 'O':
0562 return access_segment(m_outputs,4);
0563 default:
0564 break;
0565 }
0566 except("DigiEvent", "Invalid segment name: %s", name.c_str());
0567 throw std::runtime_error("Invalid segment name");
0568 }
0569
0570
0571 const DataSegment& DigiEvent::get_segment(const std::string& name) const {
0572 switch(::toupper(name[0])) {
0573 case 'I':
0574 return *m_inputs;
0575 case 'C':
0576 return *m_counts;
0577 case 'D':
0578 switch(::toupper(name[1])) {
0579 case 'E':
0580 return *m_deposits;
0581 default:
0582 return *m_data;
0583 }
0584 break;
0585 case 'O':
0586 return *m_outputs;
0587 default:
0588 break;
0589 }
0590 except("DigiEvent", "Invalid segment name: %s", name.c_str());
0591 throw std::runtime_error("Invalid segment name");
0592 }
0593
0594
0595 DataSegment& DigiEvent::get_segment(Key::segment_type id) {
0596 switch(id) {
0597 case 1:
0598 return access_segment(m_inputs,1);
0599 case 2:
0600 return access_segment(m_counts,2);
0601 case 3:
0602 return access_segment(m_deposits,3);
0603 case 4:
0604 return access_segment(m_outputs,4);
0605 case 0xAB:
0606 return access_segment(m_data,0xAB);
0607 default:
0608 break;
0609 }
0610 except("DigiEvent", "Invalid segment identifier: %d", id);
0611 throw std::runtime_error("Invalid segment name");
0612 }
0613
0614
0615 const DataSegment& DigiEvent::get_segment(Key::segment_type id) const {
0616 switch(id) {
0617 case 1:
0618 return *m_inputs;
0619 case 2:
0620 return *m_counts;
0621 case 3:
0622 return *m_deposits;
0623 case 4:
0624 return *m_outputs;
0625 case 0xAB:
0626 return *m_data;
0627 default:
0628 break;
0629 }
0630 except("DigiEvent", "Invalid segment identifier: %d", id);
0631 throw std::runtime_error("Invalid segment name");
0632 }
0633