Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:14:08

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 
0014 // Framework include files
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 // C/C++ include files
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 /// Generate key using hash algorithm
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 /// Set key submask
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 /// Access key name (if registered properly)
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 /// Update history
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 /// Drop history information
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 /// Retrieve the weighted momentum of all contributing particles
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 /// Update the deposit using deposit weighting
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 /// Update the deposit using deposit weighting
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 /// Merge new deposit map onto existing map
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 /// Merge new deposit map onto existing map (keep inputs)
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 /// Merge new deposit map onto existing map (keep inputs)
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 /// Merge new deposit map onto existing map (keep inputs)
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 /// Access energy deposit by key
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 /// Access energy deposit by key
0239 const EnergyDeposit& DepositVector::at(std::size_t cell)   const    {
0240   return data.at(cell).second;
0241 }
0242 
0243 /// Remove entry
0244 void DepositVector::remove(iterator /* position */)   {
0245   //data.erase(position);
0246 }
0247 
0248 /// Merge new deposit map onto existing map
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 /// Merge new deposit map onto existing map
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 /// Merge new deposit map onto existing map (keep inputs)
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 /// Merge new deposit map onto existing map (keep inputs)
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 /// Emplace entry
0297 void DepositMapping::emplace(CellID cell, EnergyDeposit&& deposit)    {
0298   data.emplace(cell, std::move(deposit));
0299 }
0300 
0301 /// Access energy deposit by key
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 /// Remove entry
0311 void DepositMapping::remove(iterator position)   {
0312   data.erase(position);
0313 }
0314 
0315 /// Move particle
0316 void Particle::move_position(const Position& delta)    {
0317   this->start_position += delta;
0318   this->end_position += delta;
0319 }
0320 
0321 /// Merge new deposit map onto existing map
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 /// Merge new deposit map onto existing map
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/*particle_data.history.has_value()*/));
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/*particle_data.history.has_value()*/));
0352   }
0353 }
0354 
0355 /// Insert new entry
0356 void ParticleMapping::emplace(Key particle_key, Particle&& particle_data)  {
0357   data.emplace(particle_key, std::move(particle_data));
0358 }
0359 
0360 /// Access particle by key
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 /// Merge new deposit map onto existing map (not thread safe!)
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 /// Merge new deposit map onto existing map (not thread safe!)
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 /// Merge new deposit map onto existing map (not thread safe!)
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 /// Merge new deposit map onto existing map (not thread safe!)
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 /// Initializing constructor
0405 DataSegment::DataSegment(std::mutex& l, Key::segment_type i)
0406   : data(), lock(l), id(i)
0407 {
0408 }
0409 
0410 /// Remove data item from segment
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 /// Access  data size
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 /// Remove data item from segment
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 /// Remove data items from segment (locked)
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 /// Print segment keys
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 /// Call on failed any-casts during data requests
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 /// Call on failed data requests during data requests
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 /// Access data item by key
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 /// Access data item by key  (CONST)
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 /// Intializing constructor
0514 DigiEvent::DigiEvent()
0515 {
0516   InstanceCount::increment(this);
0517 }
0518 
0519 /// Intializing constructor
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 /// Default destructor
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   /// Check again after holding the lock:
0540   if ( !segment )   {
0541     segment = std::make_unique<DataSegment>(this->m_lock, id);
0542   }
0543   return *segment;
0544 }
0545 
0546 /// Retrieve data segment from the event structure
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 /// Retrieve data segment from the event structure
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 /// Retrieve data segment from the event structure by identifier
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 /// Retrieve data segment from the event structure by identifier
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