Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-08 08:23:11

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/Primitives.h>
0016 #include <DD4hep/Printout.h>
0017 #include "DigiIO.h"
0018 
0019 
0020 /// C/C++ include files
0021 #include <limits>
0022 
0023 // =========================================================================
0024 //  EDM4HEP specific stuff
0025 // =========================================================================
0026 #ifdef DD4HEP_USE_EDM4HEP
0027 
0028 /// edm4hep include files
0029 #include <edm4hep/SimTrackerHit.h>
0030 #include <edm4hep/MCParticle.h>
0031 #include <edm4hep/MCParticleCollection.h>
0032 #if __has_include("edm4hep/TrackerHitCollection.h")
0033 #include <edm4hep/TrackerHitCollection.h>
0034 namespace edm4hep {
0035   using TrackerHit3DCollection = edm4hep::TrackerHitCollection;
0036 }
0037 #else
0038 #include <edm4hep/TrackerHit3DCollection.h>
0039 #endif
0040 #include <edm4hep/SimTrackerHitCollection.h>
0041 #include <edm4hep/CalorimeterHitCollection.h>
0042 #include <edm4hep/SimCalorimeterHitCollection.h>
0043 #include <edm4hep/EventHeaderCollection.h>
0044 #include <edm4hep/EDM4hepVersion.h>
0045 #include <podio/GenericParameters.h>
0046 
0047 /// Namespace for the AIDA detector description toolkit
0048 namespace dd4hep {
0049 
0050   /// Namespace for the Digitization part of the AIDA detector description toolkit
0051   namespace digi {
0052 
0053     struct bla  {
0054       class my_part;
0055       typedef my_part particle_type;
0056     };
0057 
0058     edm4hep::Vector3d _toVectorD(const Position& ep);
0059     edm4hep::Vector3f _toVectorF(const Position& ep);
0060 
0061     /// Structure definitions for DDDigi input data
0062     /**
0063      *
0064      *  \author  M.Frank
0065      *  \version 1.0
0066      *  \ingroup DD4HEP_DIGITIZATION
0067      */
0068     struct digi_input  {
0069       typedef Particle particle_type;
0070       struct  input_trackerhit_type     {};
0071       struct  input_calorimeterhit_type {};
0072     };
0073 
0074     /// Structure definitions for edm4hep input data
0075     /**
0076      *
0077      *  \author  M.Frank
0078      *  \version 1.0
0079      *  \ingroup DD4HEP_DIGITIZATION
0080      */
0081     struct edm4hep_input  {
0082       typedef edm4hep::MutableMCParticle particle_type;
0083       struct  input_trackerhit_type     {};
0084       struct  input_calorimeterhit_type {};
0085     };
0086 
0087     /// Structure definitions for DDG4 input data
0088     /**
0089      *
0090      *  \author  M.Frank
0091      *  \version 1.0
0092      *  \ingroup DD4HEP_DIGITIZATION
0093      */
0094     struct ddg4_input  {
0095       typedef sim::Geant4Particle particle_type;
0096       struct  input_trackerhit_type {};
0097       struct  input_calorimeterhit_type {};
0098     };
0099 
0100     template <typename T> struct data_input   {
0101       using particle_t       = typename T::particle_type;
0102       using trackerhit_t     = typename T::input_trackerhit_type;
0103       using calorimeterhit_t = typename T::input_calorimeterhit_type;
0104       using pwrap_t          = std::shared_ptr<particle_t>;
0105       using twrap_t          = std::shared_ptr<trackerhit_t>;
0106       using cwrap_t          = std::shared_ptr<calorimeterhit_t>;
0107     };
0108 
0109     edm4hep::Vector3d _toVectorD(const dd4hep::Position& ep)  {
0110       return { ep.x(), ep.y(), ep.z() };
0111     }
0112 
0113     edm4hep::Vector3f _toVectorF(const dd4hep::Position& ep)  {
0114       return { float(ep.x()), float(ep.y()), float(ep.z()) };
0115     }
0116 
0117     template <typename POSITION> Position _toPosition(const POSITION& pos)  {
0118       return { pos.x, pos.y, pos.z };
0119     }
0120 
0121     namespace {
0122       template <typename DATA> bool internal_can_handle(const DATA&, const std::type_info&)   {
0123         return true;
0124       }
0125       template <> bool internal_can_handle(const ParticleMapping::value_type& data, const std::type_info& info)   {
0126         return (data.second.source.type() == info);
0127       }
0128     }
0129 
0130     template <typename INPUT, typename DATA>
0131     static bool _can_handle(const INPUT& , const DATA& data)  {
0132       return internal_can_handle(data, typeid(typename data_input<INPUT>::pwrap_t));
0133     }
0134 
0135     template <typename CONT>
0136     void _pre_create(CONT* coll, std::size_t n)  {
0137       /// We have to pre-create all objects to be able to fill the parent-daughter relationships
0138       for ( std::size_t i=0; i<n; ++i )   {
0139         coll->create();
0140       }
0141     }
0142 
0143     template <typename INPUT, typename CONT>
0144     std::vector<const typename INPUT::particle_t*> _to_vector(const INPUT&, const CONT& cont)   {
0145       std::vector<const typename INPUT::particle_t*> vec;
0146       vec.reserve(cont.size());
0147       for ( const auto& part : cont )   {
0148         const auto& p = part.second;
0149         if ( p.source.type() == typeid(typename INPUT::pwrap_t) )   {
0150           const auto* ptr = std::any_cast<typename INPUT::pwrap_t>(&p.source);
0151           vec.emplace_back(ptr->get());
0152         }
0153       }
0154       if ( cont.size() != vec.size() )   {
0155         except("data_io","_to_vector: Containers of mixed origin are not supported!");
0156       }
0157       return vec;
0158     }
0159 
0160     template <typename T> template <typename FIRST, typename SECOND>
0161     void data_io<T>::_to_edm4hep(const FIRST&, SECOND)  {
0162       except("data_io::_to_edm4hep","(%s&, %s): Implementation not present!",
0163              typeName(typeid(FIRST)).c_str(), typeName(typeid(SECOND)).c_str());
0164     }
0165 
0166     /// Set all properties of the MutableMCParticle
0167     template <> template <>
0168     void data_io<digi_input>::_to_edm4hep(const Particle& p, 
0169                                           edm4hep::MutableMCParticle mcp)  {
0170       mcp.setPDG(p.pdgID);
0171       mcp.setTime(p.time);
0172       mcp.setMass(p.mass);
0173       mcp.setCharge(3.0*p.charge);
0174       mcp.setVertex( _toVectorD(p.start_position) );
0175       mcp.setEndpoint( _toVectorD(p.end_position) );
0176 #if EDM4HEP_BUILD_VERSION < EDM4HEP_VERSION(0, 99, 0)
0177       mcp.setMomentum( _toVectorF(p.momentum) );
0178       mcp.setMomentumAtEndpoint( _toVectorF(p.momentum) );
0179 #else
0180       mcp.setMomentum( _toVectorD(p.momentum) );
0181       mcp.setMomentumAtEndpoint( _toVectorD(p.momentum) );
0182 #endif
0183     }
0184 
0185     template <> template <>
0186     void data_io<digi_input>::_to_edm4hep(const std::vector<const Particle*>& cont,
0187                                           edm4hep::MCParticleCollection* coll)   {
0188       std::size_t i, n = cont.size();
0189       _pre_create(coll, n);
0190       /// Convert particle body
0191       for ( i=0; i<n; ++i)   {
0192         _to_edm4hep(*cont[i], coll->at(i));
0193       }
0194     }
0195 
0196     /// Set all properties of the MutableMCParticle
0197     template <> template <>
0198     void data_io<edm4hep_input>::_to_edm4hep(const edm4hep::MCParticle& p, 
0199                                              edm4hep::MutableMCParticle mcp)
0200     {
0201       mcp.setPDG( p.getPDG() );
0202       mcp.setMomentum( p.getMomentum() );
0203       mcp.setMomentumAtEndpoint( p.getMomentumAtEndpoint() );
0204       mcp.setVertex(   p.getVertex() );
0205       mcp.setEndpoint( p.getEndpoint() );
0206       mcp.setTime( p.getTime() );
0207       mcp.setMass( p.getMass() );
0208       mcp.setCharge( p.getCharge() );
0209       mcp.setGeneratorStatus( p.getGeneratorStatus() );
0210       mcp.setSimulatorStatus( p.getSimulatorStatus() );
0211 #ifdef EDM4HEP_MCPARTICLE_HAS_HELICITY
0212       mcp.setHelicity(p.getHelicity());
0213 #else
0214       mcp.setSpin(p.getSpin());
0215 #endif
0216     }
0217 
0218     template <> template <>
0219     void data_io<edm4hep_input>::_to_edm4hep(const std::vector<const edm4hep::MCParticle*>& cont,
0220                                              edm4hep::MCParticleCollection* coll)
0221     {
0222       std::size_t i, n = cont.size();
0223       _pre_create(coll, n);
0224       /// Convert particle body
0225       for ( i=0; i<n; ++i)   {
0226         const auto* p = cont[i];
0227         auto mcp = coll->at(i);
0228         _to_edm4hep(*p, mcp);
0229 #if 0
0230         /// Relationships are already resolved and kept in order: Just copy indices
0231         for (std::size_t idau = 0; idau < p->daughters_size(); ++idau)  {
0232           mcp.addToDaughters(coll->at(idau));
0233         }
0234         for (auto ipar : p->parents)   {
0235           mcp.addToParents(coll->at(ipar));
0236         }
0237 #endif
0238       }
0239     }
0240 
0241     template <> template <> 
0242     void data_io<edm4hep_input>::_to_edm4hep(const std::pair<const CellID, EnergyDeposit>& dep,
0243                          const std::array<float, 6>& covMat,
0244                          edm4hep::TrackerHit3DCollection& collection,
0245                          int hit_type)
0246 
0247     {
0248       const EnergyDeposit& de = dep.second;
0249       auto hit = collection.create();
0250       double dep_error = de.depositError;
0251       if ( dep_error < -std::numeric_limits<double>::epsilon() )   {
0252         dep_error = 0e0;
0253       }
0254       hit.setType( hit_type );
0255       hit.setTime( de.time );
0256       hit.setCovMatrix( covMat );
0257       hit.setCellID( dep.first );
0258       hit.setEDep( de.deposit );
0259       hit.setEDepError( dep_error );
0260       //hit.setEdx( de.deposit/de.length );
0261       hit.setPosition( _toVectorD(de.position) );
0262     }
0263 
0264     template <> template <>
0265     void data_io<edm4hep_input>::_to_edm4hep(const std::pair<const CellID, EnergyDeposit>& dep,
0266                          edm4hep::CalorimeterHitCollection& collection,
0267                          int hit_type)
0268     {
0269       const EnergyDeposit& de = dep.second;
0270       auto hit = collection.create();
0271       double dep_error = de.depositError;
0272       if ( dep_error < -std::numeric_limits<double>::epsilon() )   {
0273         dep_error = 0e0;
0274       }
0275       hit.setType( hit_type );
0276       hit.setTime( de.time );
0277       hit.setCellID( dep.first );
0278       hit.setEnergy( de.deposit );
0279       hit.setEnergyError( dep_error );
0280       hit.setPosition( _toVectorF(de.position) );
0281     }
0282 
0283     template <> template <>
0284     void data_io<edm4hep_input>::_to_digi(Key key, 
0285                       const edm4hep::MCParticleCollection& input,
0286                       ParticleMapping& particles)
0287     {
0288       Key mkey = key;
0289       for( std::size_t i=0, n=input.size(); i<n; ++i )  {
0290     Particle part {};
0291     edm4hep::MCParticle p = input.at(i);
0292         part.start_position = _toPosition(p.getVertex());
0293         part.end_position   = _toPosition(p.getEndpoint());
0294         part.momentum       = _toPosition(p.getMomentum());
0295         part.pdgID          = p.getPDG();
0296         part.charge         = 3.0*p.getCharge();
0297         part.mass           = p.getMass();
0298         part.time           = p.getTime();
0299         mkey.set_item(particles.size());
0300         part.source = std::make_any<edm4hep::MCParticle>(std::move(p));
0301         particles.push(mkey, std::move(part));
0302       }
0303     }
0304 
0305     template <> template <>
0306     bool DepositPredicate<EnergyCut>::operator()(edm4hep::SimTrackerHit h)  const   {
0307       return h.getEDep() > data.cutoff;
0308     }
0309 
0310     template <> template <>
0311     void data_io<edm4hep_input>::_to_digi_if(const edm4hep::SimTrackerHitCollection& input,
0312                          std::map<CellID, edm4hep::SimTrackerHit>& hits,
0313                          const DepositPredicate<EnergyCut>& predicate)   {
0314       for( std::size_t i=0, n=input.size(); i<n; ++i )  {
0315     auto p = input.at(i);
0316         if ( predicate(p) )   {
0317           CellID cell = p.getCellID();
0318           hits.emplace(cell, std::move(p));
0319         }
0320       }
0321     }
0322 
0323     /// Import edm4hep SimTrackerHit collections
0324     template <> template <>
0325     void data_io<edm4hep_input>::_to_digi(Key key,
0326                       const std::map<CellID, edm4hep::SimTrackerHit>& hits,
0327                       DepositVector& out)  {
0328       out.data_type = SegmentEntry::CALORIMETER_HITS;
0329       for( const auto& depo : hits )   {
0330     Key history_key;
0331     EnergyDeposit dep { };
0332     const auto& h = depo.second;
0333     dep.flag = h.getQuality();
0334     dep.time = h.getTime();
0335     dep.length = h.getPathLength();
0336     dep.deposit = h.getEDep();
0337     dep.position = _toPosition(h.getPosition());
0338     dep.momentum = _toPosition(h.getMomentum());
0339     history_key.set_mask(key.mask());
0340     history_key.set_item(out.size());
0341     history_key.set_segment(key.segment());
0342     dep.history.hits.emplace_back(history_key, dep.deposit);
0343     //add_particle_history(h, history_key, dep.history);
0344     out.emplace(depo.first, std::move(dep));
0345       }
0346     }
0347 
0348     /// Import edm4hep EventHeader collections
0349     template <> template <>
0350     void data_io<edm4hep_input>::_to_digi(Key /* key */,
0351                       const edm4hep::EventHeaderCollection& headers,
0352                       dd4hep::digi::DataParameters& params)  {
0353       for( unsigned int i=0, n=headers.size(); i < n; ++i)   {
0354     const auto& hdr = headers[i];
0355     params.setRunNumber(hdr.getRunNumber());
0356     params.setEventNumber(hdr.getEventNumber());
0357     params.setTimeStamp(hdr.getTimeStamp());
0358     params.setWeight(hdr.getWeight());
0359     break;
0360       }
0361     }
0362 
0363     /// Import parameters from podio frame
0364     template <> template <>
0365     void data_io<edm4hep_input>::_to_digi(Key /* key */,
0366                       const podio::GenericParameters& inputparams,
0367                       dd4hep::digi::DataParameters&   parameters)  {
0368       /// Now copy all frame parameters to the data header
0369       parameters.data->stringParams = inputparams.getMap<std::string>();
0370       parameters.data->floatParams  = inputparams.getMap<float>();
0371       parameters.data->intParams    = inputparams.getMap<int>();
0372     }
0373 
0374     template <> template <>
0375     bool DepositPredicate<EnergyCut>::operator()(edm4hep::SimCalorimeterHit h)  const   {
0376       return h.getEnergy() > data.cutoff;
0377     }
0378 
0379     template <> template <>
0380     void data_io<edm4hep_input>::_to_digi_if(const edm4hep::SimCalorimeterHitCollection& input,
0381                          std::map<CellID, edm4hep::SimCalorimeterHit>& hits,
0382                          const DepositPredicate<EnergyCut>& predicate)   {
0383       for( std::size_t i=0, n=input.size(); i<n; ++i )  {
0384     auto p = input.at(i);
0385         if ( predicate(p) )   {
0386           CellID cell = p.getCellID();
0387           hits.emplace(cell, std::move(p));
0388         }
0389       }
0390     }
0391 
0392     template <> template <>
0393     void data_io<edm4hep_input>::_to_digi(Key key,
0394                       const std::map<CellID, edm4hep::SimCalorimeterHit>& hits,
0395                       DepositVector& out)  {
0396       out.data_type = SegmentEntry::CALORIMETER_HITS;
0397       for( const auto& depo : hits )  {
0398     Key history_key;
0399     EnergyDeposit dep { };
0400     const auto& h = depo.second;
0401     dep.flag = 0;
0402     
0403     dep.deposit = h.getEnergy();
0404     dep.position = _toPosition(h.getPosition());
0405     history_key.set_mask(key.mask());
0406     history_key.set_item(out.size());
0407     history_key.set_segment(key.segment());
0408     dep.history.hits.emplace_back(history_key, dep.deposit);
0409     //add_particle_history(h, history_key, dep.history);
0410     out.emplace(depo.first, std::move(dep));
0411       }
0412     }
0413 
0414   }     // End namespace digi
0415 }       // End namespace dd4hep
0416 #endif  // DD4HEP_USE_EDM4HEP
0417 
0418 /// =========================================================================
0419 ///  Conversion from DDG4 in memory to DDDigi
0420 /// =========================================================================
0421 #if defined(DD4HEP_USE_DDG4)
0422 
0423 #include <DDG4/Geant4Data.h>
0424 #include <DDG4/Geant4Particle.h>
0425 
0426 /// Namespace for the AIDA detector description toolkit
0427 namespace dd4hep {
0428 
0429   /// Namespace for the Digitization part of the AIDA detector description toolkit
0430   namespace digi {
0431 
0432     using PropertyMask = dd4hep::detail::ReferenceBitMask<int>;
0433 
0434     template <> template <>
0435     bool DepositPredicate<EnergyCut>::operator()(sim::Geant4Tracker::Hit* h)  const   {
0436       return h->energyDeposit > data.cutoff;
0437     }
0438 
0439     template <> template <>
0440     bool DepositPredicate<EnergyCut>::operator()(sim::Geant4Calorimeter::Hit* h)  const   {
0441       return h->energyDeposit > data.cutoff;
0442     }
0443 
0444     void add_particle_history(const sim::Geant4Calorimeter::Hit* hit, Key key, History& hist) {
0445       for( const auto& truth : hit->truth )   {
0446         key.set_item(truth.trackID);
0447         hist.particles.emplace_back(key, truth.deposit);
0448       }
0449     }
0450 
0451     void add_particle_history(const sim::Geant4Tracker::Hit* hit, Key key, History& hist)  {
0452       key.set_item(hit->truth.trackID);
0453       hist.particles.emplace_back(key, hit->truth.deposit);
0454     }
0455 
0456     template <> template <>
0457     void data_io<ddg4_input>::_to_digi_if(const std::vector<sim::Geant4Tracker::Hit*>& data,
0458                                           std::map<CellID, std::shared_ptr<sim::Geant4Tracker::Hit> >& hits,
0459                                           const DepositPredicate<EnergyCut>& predicate)   {
0460       for( auto* p : data )   {
0461         std::shared_ptr<sim::Geant4Tracker::Hit> ptr(p);
0462         if ( predicate(p) )   {
0463           CellID cell = ptr->cellID;
0464           hits.emplace(cell, std::move(ptr));
0465         }
0466       }
0467     }
0468 
0469     template <> template <>
0470     void data_io<ddg4_input>::_to_digi_if(const std::vector<sim::Geant4Calorimeter::Hit*>& data,
0471                                           std::map<CellID, std::shared_ptr<sim::Geant4Calorimeter::Hit> >& hits,
0472                                           const DepositPredicate<EnergyCut>& predicate)   {
0473       for( auto* p : data )   {
0474         std::shared_ptr<sim::Geant4Calorimeter::Hit> ptr(p);
0475         if ( predicate(p) )   {
0476           CellID cell = ptr->cellID;
0477           hits.emplace(cell, std::move(ptr));
0478         }
0479       }
0480     }
0481 
0482     template <> template <>
0483     void data_io<ddg4_input>::_to_digi(Key key, 
0484                                        const std::vector<sim::Geant4Particle*>& input,
0485                                        ParticleMapping& particles)
0486     {
0487       Key mkey = std::move(key);
0488       for( auto* part_ptr : input )   {
0489         std::shared_ptr<sim::Geant4Particle> p(part_ptr);
0490         Particle part;
0491         part.start_position = Position(p->vsx, p->vsy, p->vsz);
0492         part.end_position   = Position(p->vex, p->vey, p->vez);
0493         part.momentum       = Direction(p->psx,p->psy, p->psz);
0494         part.pdgID          = p->pdgID;
0495         part.charge         = p->charge;
0496         part.mass           = p->mass;
0497         part.time           = p->time;
0498         mkey.set_item(particles.size());
0499         part.source = std::make_any<std::shared_ptr<sim::Geant4Particle> >(std::move(p));
0500         particles.push(mkey, std::move(part));
0501       }
0502     }
0503 
0504     template <typename T>
0505     static void ddg4_cnv_to_digi(Key key,
0506                             const std::pair<const CellID, std::shared_ptr<T> >& depo,
0507                             DepositVector& out)     {
0508       Key history_key;
0509       EnergyDeposit dep { };
0510       const auto* h = depo.second.get();
0511 
0512       dep.flag = h->flag;
0513       dep.deposit = h->energyDeposit;
0514       dep.position = (h->position / dd4hep::mm);
0515 
0516       history_key.set_mask(key.mask());
0517       history_key.set_item(out.size());
0518       history_key.set_segment(key.segment());
0519       dep.history.hits.emplace_back(history_key, dep.deposit);
0520       add_particle_history(h, std::move(history_key), dep.history);
0521       out.emplace(depo.first, std::move(dep));
0522     }
0523 
0524     template <> template <>
0525     void data_io<ddg4_input>::_to_digi(Key key,
0526                                        const std::map<CellID, std::shared_ptr<sim::Geant4Calorimeter::Hit> >& hits,
0527                                        DepositVector& out)  {
0528       out.data_type = SegmentEntry::CALORIMETER_HITS;
0529       for( const auto& p : hits )
0530         ddg4_cnv_to_digi(key, p, out);
0531     }
0532 
0533     template <> template <>
0534     void data_io<ddg4_input>::_to_digi(Key key, 
0535                                        const std::map<CellID, std::shared_ptr<sim::Geant4Tracker::Hit> >& hits,
0536                                        DepositVector& out)  {
0537       out.data_type = SegmentEntry::TRACKER_HITS;
0538       for( const auto& p : hits )
0539         ddg4_cnv_to_digi(key, p, out);
0540     }
0541   }     // End namespace digi
0542 }       // End namespace dd4hep
0543 #endif  // DD4HEP_USE_DDG4
0544 
0545 /// ======================================================================
0546 ///  Conversion from DDG4 in memory to edm4hep
0547 /// ======================================================================
0548 #if defined(DD4HEP_USE_DDG4) && defined(DD4HEP_USE_EDM4HEP)
0549 
0550 /// Namespace for the AIDA detector description toolkit
0551 namespace dd4hep {
0552 
0553   /// Namespace for the Digitization part of the AIDA detector description toolkit
0554   namespace digi {
0555 
0556     /// Set all properties of the MutableMCParticle
0557     template <> template <>
0558     void data_io<ddg4_input>::_to_edm4hep(const sim::Geant4Particle& p, 
0559                                           edm4hep::MutableMCParticle mcp)
0560     {
0561       auto status = p.status;
0562       const PropertyMask mask(status);
0563       mcp.setPDG(p.pdgID);
0564 
0565 #if EDM4HEP_BUILD_VERSION < EDM4HEP_VERSION(0, 99, 0)
0566       mcp.setMomentum( _toVectorF( { p.psx, p.psy, p.psz } ) );
0567       mcp.setMomentumAtEndpoint( _toVectorF( {p.pex, p.pey, p.pez} ) );
0568 #else
0569       mcp.setMomentum( _toVectorD( { p.psx, p.psy, p.psz } ) );
0570       mcp.setMomentumAtEndpoint( _toVectorD( {p.pex, p.pey, p.pez} ) );
0571 #endif
0572       mcp.setVertex( _toVectorD( { p.vsx, p.vsy, p.vsz } ) );
0573       mcp.setEndpoint( _toVectorD( { p.vex, p.vey, p.vez } ) );
0574 
0575       mcp.setTime(p.time);
0576       mcp.setMass(p.mass);
0577       mcp.setCharge(3.0*float(p.charge));
0578 
0579       // Set generator status
0580       mcp.setGeneratorStatus(0);
0581       if( p.genStatus ) {
0582         mcp.setGeneratorStatus( p.genStatus ) ;
0583       } else {
0584         if ( mask.isSet(sim::G4PARTICLE_GEN_STABLE) )             mcp.setGeneratorStatus(1);
0585         else if ( mask.isSet(sim::G4PARTICLE_GEN_DECAYED) )       mcp.setGeneratorStatus(2);
0586         else if ( mask.isSet(sim::G4PARTICLE_GEN_DOCUMENTATION) ) mcp.setGeneratorStatus(3);
0587         else if ( mask.isSet(sim::G4PARTICLE_GEN_BEAM) )          mcp.setGeneratorStatus(4);
0588         else if ( mask.isSet(sim::G4PARTICLE_GEN_OTHER) )         mcp.setGeneratorStatus(9);
0589       }
0590 
0591       // Set simulation status
0592       mcp.setCreatedInSimulation(         mask.isSet(sim::G4PARTICLE_SIM_CREATED) );
0593       mcp.setBackscatter(                 mask.isSet(sim::G4PARTICLE_SIM_BACKSCATTER) );
0594       mcp.setVertexIsNotEndpointOfParent( mask.isSet(sim::G4PARTICLE_SIM_PARENT_RADIATED) );
0595       mcp.setDecayedInTracker(            mask.isSet(sim::G4PARTICLE_SIM_DECAY_TRACKER) );
0596       mcp.setDecayedInCalorimeter(        mask.isSet(sim::G4PARTICLE_SIM_DECAY_CALO) );
0597       mcp.setHasLeftDetector(             mask.isSet(sim::G4PARTICLE_SIM_LEFT_DETECTOR) );
0598       mcp.setStopped(                     mask.isSet(sim::G4PARTICLE_SIM_STOPPED) );
0599       mcp.setOverlay(                     false );
0600 
0601       //fg: if simstatus !=0 we have to set the generator status to 0:
0602       if( mcp.isCreatedInSimulation() )
0603         mcp.setGeneratorStatus( 0 );
0604 
0605 #ifdef EDM4HEP_MCPARTICLE_HAS_HELICITY
0606       mcp.setHelicity(p.spin[2]);
0607 #else
0608       mcp.setSpin(p.spin);
0609 #endif
0610     }
0611 
0612     template <> template <> 
0613     void data_io<ddg4_input>::_to_edm4hep(const std::vector<const sim::Geant4Particle*>& cont,
0614                                           edm4hep::MCParticleCollection* coll)
0615     {
0616       /// Precreate objects to allow setting the references without second pass
0617       std::size_t i, n = cont.size();
0618       _pre_create(coll, n);
0619       /// Convert particle body
0620       for ( i=0; i<n; ++i)   {
0621         const auto* p = cont[i];
0622         auto  mcp = coll->at(i);
0623         _to_edm4hep(*p, mcp);
0624         /// Relationships are already resolved and kept in order: Just copy indices
0625         for (auto idau : p->daughters)
0626           mcp.addToDaughters(coll->at(idau));
0627         for (auto ipar : p->parents)
0628           mcp.addToParents(coll->at(ipar));
0629       }
0630     }
0631   }     // End namespace digi
0632 }       // End namespace dd4hep
0633 #endif  // DD4HEP_USE_DDG4 && DD4HEP_USE_EDM4HEP
0634 
0635 /// ======================================================================
0636 ///  Conversion from DDDigi in memory to edm4hep
0637 /// ======================================================================
0638 #ifdef DD4HEP_USE_EDM4HEP
0639 /// Namespace for the AIDA detector description toolkit
0640 namespace dd4hep {
0641 
0642   /// Namespace for the Digitization part of the AIDA detector description toolkit
0643   namespace digi {
0644 
0645     template <> template <> 
0646     void data_io<edm4hep_input>::_to_edm4hep(const ParticleMapping& cont,
0647                          edm4hep::MCParticleCollection* coll)
0648     {
0649       if ( cont.empty() )   {
0650         return;
0651       }
0652       else if ( _can_handle(edm4hep_input(), *cont.begin()) )  {
0653         auto vec = _to_vector(data_input<edm4hep_input>(), cont);
0654         if ( !vec.empty() )  {
0655       data_io<edm4hep_input>::_to_edm4hep(vec, coll);
0656         }
0657       }
0658       else if ( _can_handle(ddg4_input(), *cont.begin()) )  {
0659         auto vec = _to_vector(data_input<ddg4_input>(), cont);
0660         if ( !vec.empty() )  {
0661           data_io<ddg4_input>::_to_edm4hep(vec, coll);
0662         }
0663       }
0664       else   {
0665     // Catch-all: convert what we have at hands
0666     auto vec = _to_vector(data_input<digi_input>(), cont);
0667     if ( !vec.empty() )  {
0668       data_io<digi_input>::_to_edm4hep(vec, coll);
0669     }
0670       }
0671     }
0672   }     // End namespace digi
0673 }       // End namespace dd4hep
0674 #endif  // DD4HEP_USE_EDM4HEP