Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-01 07:55: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       mcp.setSpin(p.getSpin());
0212     }
0213 
0214     template <> template <>
0215     void data_io<edm4hep_input>::_to_edm4hep(const std::vector<const edm4hep::MCParticle*>& cont,
0216                                              edm4hep::MCParticleCollection* coll)
0217     {
0218       std::size_t i, n = cont.size();
0219       _pre_create(coll, n);
0220       /// Convert particle body
0221       for ( i=0; i<n; ++i)   {
0222         const auto* p = cont[i];
0223         auto mcp = coll->at(i);
0224         _to_edm4hep(*p, mcp);
0225 #if 0
0226         /// Relationships are already resolved and kept in order: Just copy indices
0227         for (std::size_t idau = 0; idau < p->daughters_size(); ++idau)  {
0228           mcp.addToDaughters(coll->at(idau));
0229         }
0230         for (auto ipar : p->parents)   {
0231           mcp.addToParents(coll->at(ipar));
0232         }
0233 #endif
0234       }
0235     }
0236 
0237     template <> template <> 
0238     void data_io<edm4hep_input>::_to_edm4hep(const std::pair<const CellID, EnergyDeposit>& dep,
0239                          const std::array<float, 6>& covMat,
0240                          edm4hep::TrackerHit3DCollection& collection,
0241                          int hit_type)
0242 
0243     {
0244       const EnergyDeposit& de = dep.second;
0245       auto hit = collection.create();
0246       double dep_error = de.depositError;
0247       if ( dep_error < -std::numeric_limits<double>::epsilon() )   {
0248         dep_error = 0e0;
0249       }
0250       hit.setType( hit_type );
0251       hit.setTime( de.time );
0252       hit.setCovMatrix( covMat );
0253       hit.setCellID( dep.first );
0254       hit.setEDep( de.deposit );
0255       hit.setEDepError( dep_error );
0256       //hit.setEdx( de.deposit/de.length );
0257       hit.setPosition( _toVectorD(de.position) );
0258     }
0259 
0260     template <> template <>
0261     void data_io<edm4hep_input>::_to_edm4hep(const std::pair<const CellID, EnergyDeposit>& dep,
0262                          edm4hep::CalorimeterHitCollection& collection,
0263                          int hit_type)
0264     {
0265       const EnergyDeposit& de = dep.second;
0266       auto hit = collection.create();
0267       double dep_error = de.depositError;
0268       if ( dep_error < -std::numeric_limits<double>::epsilon() )   {
0269         dep_error = 0e0;
0270       }
0271       hit.setType( hit_type );
0272       hit.setTime( de.time );
0273       hit.setCellID( dep.first );
0274       hit.setEnergy( de.deposit );
0275       hit.setEnergyError( dep_error );
0276       hit.setPosition( _toVectorF(de.position) );
0277     }
0278 
0279     template <> template <>
0280     void data_io<edm4hep_input>::_to_digi(Key key, 
0281                       const edm4hep::MCParticleCollection& input,
0282                       ParticleMapping& particles)
0283     {
0284       Key mkey = key;
0285       for( std::size_t i=0, n=input.size(); i<n; ++i )  {
0286     Particle part {};
0287     edm4hep::MCParticle p = input.at(i);
0288         part.start_position = _toPosition(p.getVertex());
0289         part.end_position   = _toPosition(p.getEndpoint());
0290         part.momentum       = _toPosition(p.getMomentum());
0291         part.pdgID          = p.getPDG();
0292         part.charge         = 3.0*p.getCharge();
0293         part.mass           = p.getMass();
0294         part.time           = p.getTime();
0295         mkey.set_item(particles.size());
0296         part.source = std::make_any<edm4hep::MCParticle>(std::move(p));
0297         particles.push(mkey, std::move(part));
0298       }
0299     }
0300 
0301     template <> template <>
0302     bool DepositPredicate<EnergyCut>::operator()(edm4hep::SimTrackerHit h)  const   {
0303       return h.getEDep() > data.cutoff;
0304     }
0305 
0306     template <> template <>
0307     void data_io<edm4hep_input>::_to_digi_if(const edm4hep::SimTrackerHitCollection& input,
0308                          std::map<CellID, edm4hep::SimTrackerHit>& hits,
0309                          const DepositPredicate<EnergyCut>& predicate)   {
0310       for( std::size_t i=0, n=input.size(); i<n; ++i )  {
0311     auto p = input.at(i);
0312         if ( predicate(p) )   {
0313           CellID cell = p.getCellID();
0314           hits.emplace(cell, std::move(p));
0315         }
0316       }
0317     }
0318 
0319     /// Import edm4hep SimTrackerHit collections
0320     template <> template <>
0321     void data_io<edm4hep_input>::_to_digi(Key key,
0322                       const std::map<CellID, edm4hep::SimTrackerHit>& hits,
0323                       DepositVector& out)  {
0324       out.data_type = SegmentEntry::CALORIMETER_HITS;
0325       for( const auto& depo : hits )   {
0326     Key history_key;
0327     EnergyDeposit dep { };
0328     const auto& h = depo.second;
0329     dep.flag = h.getQuality();
0330     dep.time = h.getTime();
0331     dep.length = h.getPathLength();
0332     dep.deposit = h.getEDep();
0333     dep.position = _toPosition(h.getPosition());
0334     dep.momentum = _toPosition(h.getMomentum());
0335     history_key.set_mask(key.mask());
0336     history_key.set_item(out.size());
0337     history_key.set_segment(key.segment());
0338     dep.history.hits.emplace_back(history_key, dep.deposit);
0339     //add_particle_history(h, history_key, dep.history);
0340     out.emplace(depo.first, std::move(dep));
0341       }
0342     }
0343 
0344     /// Import edm4hep EventHeader collections
0345     template <> template <>
0346     void data_io<edm4hep_input>::_to_digi(Key /* key */,
0347                       const edm4hep::EventHeaderCollection& headers,
0348                       dd4hep::digi::DataParameters& params)  {
0349       for( unsigned int i=0, n=headers.size(); i < n; ++i)   {
0350     const auto& hdr = headers[i];
0351     params.setRunNumber(hdr.getRunNumber());
0352     params.setEventNumber(hdr.getEventNumber());
0353     params.setTimeStamp(hdr.getTimeStamp());
0354     params.setWeight(hdr.getWeight());
0355     break;
0356       }
0357     }
0358 
0359     /// Import parameters from podio frame
0360     template <> template <>
0361     void data_io<edm4hep_input>::_to_digi(Key /* key */,
0362                       const podio::GenericParameters& inputparams,
0363                       dd4hep::digi::DataParameters&   parameters)  {
0364       /// Now copy all frame parameters to the data header
0365       parameters.data->stringParams = inputparams.getMap<std::string>();
0366       parameters.data->floatParams  = inputparams.getMap<float>();
0367       parameters.data->intParams    = inputparams.getMap<int>();
0368     }
0369 
0370     template <> template <>
0371     bool DepositPredicate<EnergyCut>::operator()(edm4hep::SimCalorimeterHit h)  const   {
0372       return h.getEnergy() > data.cutoff;
0373     }
0374 
0375     template <> template <>
0376     void data_io<edm4hep_input>::_to_digi_if(const edm4hep::SimCalorimeterHitCollection& input,
0377                          std::map<CellID, edm4hep::SimCalorimeterHit>& hits,
0378                          const DepositPredicate<EnergyCut>& predicate)   {
0379       for( std::size_t i=0, n=input.size(); i<n; ++i )  {
0380     auto p = input.at(i);
0381         if ( predicate(p) )   {
0382           CellID cell = p.getCellID();
0383           hits.emplace(cell, std::move(p));
0384         }
0385       }
0386     }
0387 
0388     template <> template <>
0389     void data_io<edm4hep_input>::_to_digi(Key key,
0390                       const std::map<CellID, edm4hep::SimCalorimeterHit>& hits,
0391                       DepositVector& out)  {
0392       out.data_type = SegmentEntry::CALORIMETER_HITS;
0393       for( const auto& depo : hits )  {
0394     Key history_key;
0395     EnergyDeposit dep { };
0396     const auto& h = depo.second;
0397     dep.flag = 0;
0398     
0399     dep.deposit = h.getEnergy();
0400     dep.position = _toPosition(h.getPosition());
0401     history_key.set_mask(key.mask());
0402     history_key.set_item(out.size());
0403     history_key.set_segment(key.segment());
0404     dep.history.hits.emplace_back(history_key, dep.deposit);
0405     //add_particle_history(h, history_key, dep.history);
0406     out.emplace(depo.first, std::move(dep));
0407       }
0408     }
0409 
0410   }     // End namespace digi
0411 }       // End namespace dd4hep
0412 #endif  // DD4HEP_USE_EDM4HEP
0413 
0414 /// =========================================================================
0415 ///  Conversion from DDG4 in memory to DDDigi
0416 /// =========================================================================
0417 #if defined(DD4HEP_USE_DDG4)
0418 
0419 #include <DDG4/Geant4Data.h>
0420 #include <DDG4/Geant4Particle.h>
0421 
0422 /// Namespace for the AIDA detector description toolkit
0423 namespace dd4hep {
0424 
0425   /// Namespace for the Digitization part of the AIDA detector description toolkit
0426   namespace digi {
0427 
0428     using PropertyMask = dd4hep::detail::ReferenceBitMask<int>;
0429 
0430     template <> template <>
0431     bool DepositPredicate<EnergyCut>::operator()(sim::Geant4Tracker::Hit* h)  const   {
0432       return h->energyDeposit > data.cutoff;
0433     }
0434 
0435     template <> template <>
0436     bool DepositPredicate<EnergyCut>::operator()(sim::Geant4Calorimeter::Hit* h)  const   {
0437       return h->energyDeposit > data.cutoff;
0438     }
0439 
0440     void add_particle_history(const sim::Geant4Calorimeter::Hit* hit, Key key, History& hist) {
0441       for( const auto& truth : hit->truth )   {
0442         key.set_item(truth.trackID);
0443         hist.particles.emplace_back(key, truth.deposit);
0444       }
0445     }
0446 
0447     void add_particle_history(const sim::Geant4Tracker::Hit* hit, Key key, History& hist)  {
0448       key.set_item(hit->truth.trackID);
0449       hist.particles.emplace_back(key, hit->truth.deposit);
0450     }
0451 
0452     template <> template <>
0453     void data_io<ddg4_input>::_to_digi_if(const std::vector<sim::Geant4Tracker::Hit*>& data,
0454                                           std::map<CellID, std::shared_ptr<sim::Geant4Tracker::Hit> >& hits,
0455                                           const DepositPredicate<EnergyCut>& predicate)   {
0456       for( auto* p : data )   {
0457         std::shared_ptr<sim::Geant4Tracker::Hit> ptr(p);
0458         if ( predicate(p) )   {
0459           CellID cell = ptr->cellID;
0460           hits.emplace(cell, std::move(ptr));
0461         }
0462       }
0463     }
0464 
0465     template <> template <>
0466     void data_io<ddg4_input>::_to_digi_if(const std::vector<sim::Geant4Calorimeter::Hit*>& data,
0467                                           std::map<CellID, std::shared_ptr<sim::Geant4Calorimeter::Hit> >& hits,
0468                                           const DepositPredicate<EnergyCut>& predicate)   {
0469       for( auto* p : data )   {
0470         std::shared_ptr<sim::Geant4Calorimeter::Hit> ptr(p);
0471         if ( predicate(p) )   {
0472           CellID cell = ptr->cellID;
0473           hits.emplace(cell, std::move(ptr));
0474         }
0475       }
0476     }
0477 
0478     template <> template <>
0479     void data_io<ddg4_input>::_to_digi(Key key, 
0480                                        const std::vector<sim::Geant4Particle*>& input,
0481                                        ParticleMapping& particles)
0482     {
0483       Key mkey = std::move(key);
0484       for( auto* part_ptr : input )   {
0485         std::shared_ptr<sim::Geant4Particle> p(part_ptr);
0486         Particle part;
0487         part.start_position = Position(p->vsx, p->vsy, p->vsz);
0488         part.end_position   = Position(p->vex, p->vey, p->vez);
0489         part.momentum       = Direction(p->psx,p->psy, p->psz);
0490         part.pdgID          = p->pdgID;
0491         part.charge         = p->charge;
0492         part.mass           = p->mass;
0493         part.time           = p->time;
0494         mkey.set_item(particles.size());
0495         part.source = std::make_any<std::shared_ptr<sim::Geant4Particle> >(std::move(p));
0496         particles.push(mkey, std::move(part));
0497       }
0498     }
0499 
0500     template <typename T>
0501     static void ddg4_cnv_to_digi(Key key,
0502                             const std::pair<const CellID, std::shared_ptr<T> >& depo,
0503                             DepositVector& out)     {
0504       Key history_key;
0505       EnergyDeposit dep { };
0506       const auto* h = depo.second.get();
0507 
0508       dep.flag = h->flag;
0509       dep.deposit = h->energyDeposit;
0510       dep.position = (h->position / dd4hep::mm);
0511 
0512       history_key.set_mask(key.mask());
0513       history_key.set_item(out.size());
0514       history_key.set_segment(key.segment());
0515       dep.history.hits.emplace_back(history_key, dep.deposit);
0516       add_particle_history(h, std::move(history_key), dep.history);
0517       out.emplace(depo.first, std::move(dep));
0518     }
0519 
0520     template <> template <>
0521     void data_io<ddg4_input>::_to_digi(Key key,
0522                                        const std::map<CellID, std::shared_ptr<sim::Geant4Calorimeter::Hit> >& hits,
0523                                        DepositVector& out)  {
0524       out.data_type = SegmentEntry::CALORIMETER_HITS;
0525       for( const auto& p : hits )
0526         ddg4_cnv_to_digi(key, p, out);
0527     }
0528 
0529     template <> template <>
0530     void data_io<ddg4_input>::_to_digi(Key key, 
0531                                        const std::map<CellID, std::shared_ptr<sim::Geant4Tracker::Hit> >& hits,
0532                                        DepositVector& out)  {
0533       out.data_type = SegmentEntry::TRACKER_HITS;
0534       for( const auto& p : hits )
0535         ddg4_cnv_to_digi(key, p, out);
0536     }
0537   }     // End namespace digi
0538 }       // End namespace dd4hep
0539 #endif  // DD4HEP_USE_DDG4
0540 
0541 /// ======================================================================
0542 ///  Conversion from DDG4 in memory to edm4hep
0543 /// ======================================================================
0544 #if defined(DD4HEP_USE_DDG4) && defined(DD4HEP_USE_EDM4HEP)
0545 
0546 /// Namespace for the AIDA detector description toolkit
0547 namespace dd4hep {
0548 
0549   /// Namespace for the Digitization part of the AIDA detector description toolkit
0550   namespace digi {
0551 
0552     /// Set all properties of the MutableMCParticle
0553     template <> template <>
0554     void data_io<ddg4_input>::_to_edm4hep(const sim::Geant4Particle& p, 
0555                                           edm4hep::MutableMCParticle mcp)
0556     {
0557       auto status = p.status;
0558       const PropertyMask mask(status);
0559       mcp.setPDG(p.pdgID);
0560 
0561 #if EDM4HEP_BUILD_VERSION < EDM4HEP_VERSION(0, 99, 0)
0562       mcp.setMomentum( _toVectorF( { p.psx, p.psy, p.psz } ) );
0563       mcp.setMomentumAtEndpoint( _toVectorF( {p.pex, p.pey, p.pez} ) );
0564 #else
0565       mcp.setMomentum( _toVectorD( { p.psx, p.psy, p.psz } ) );
0566       mcp.setMomentumAtEndpoint( _toVectorD( {p.pex, p.pey, p.pez} ) );
0567 #endif
0568       mcp.setVertex( _toVectorD( { p.vsx, p.vsy, p.vsz } ) );
0569       mcp.setEndpoint( _toVectorD( { p.vex, p.vey, p.vez } ) );
0570 
0571       mcp.setTime(p.time);
0572       mcp.setMass(p.mass);
0573       mcp.setCharge(3.0*float(p.charge));
0574 
0575       // Set generator status
0576       mcp.setGeneratorStatus(0);
0577       if( p.genStatus ) {
0578         mcp.setGeneratorStatus( p.genStatus ) ;
0579       } else {
0580         if ( mask.isSet(sim::G4PARTICLE_GEN_STABLE) )             mcp.setGeneratorStatus(1);
0581         else if ( mask.isSet(sim::G4PARTICLE_GEN_DECAYED) )       mcp.setGeneratorStatus(2);
0582         else if ( mask.isSet(sim::G4PARTICLE_GEN_DOCUMENTATION) ) mcp.setGeneratorStatus(3);
0583         else if ( mask.isSet(sim::G4PARTICLE_GEN_BEAM) )          mcp.setGeneratorStatus(4);
0584         else if ( mask.isSet(sim::G4PARTICLE_GEN_OTHER) )         mcp.setGeneratorStatus(9);
0585       }
0586 
0587       // Set simulation status
0588       mcp.setCreatedInSimulation(         mask.isSet(sim::G4PARTICLE_SIM_CREATED) );
0589       mcp.setBackscatter(                 mask.isSet(sim::G4PARTICLE_SIM_BACKSCATTER) );
0590       mcp.setVertexIsNotEndpointOfParent( mask.isSet(sim::G4PARTICLE_SIM_PARENT_RADIATED) );
0591       mcp.setDecayedInTracker(            mask.isSet(sim::G4PARTICLE_SIM_DECAY_TRACKER) );
0592       mcp.setDecayedInCalorimeter(        mask.isSet(sim::G4PARTICLE_SIM_DECAY_CALO) );
0593       mcp.setHasLeftDetector(             mask.isSet(sim::G4PARTICLE_SIM_LEFT_DETECTOR) );
0594       mcp.setStopped(                     mask.isSet(sim::G4PARTICLE_SIM_STOPPED) );
0595       mcp.setOverlay(                     false );
0596 
0597       //fg: if simstatus !=0 we have to set the generator status to 0:
0598       if( mcp.isCreatedInSimulation() )
0599         mcp.setGeneratorStatus( 0 );
0600 
0601       mcp.setSpin(p.spin);
0602     }
0603 
0604     template <> template <> 
0605     void data_io<ddg4_input>::_to_edm4hep(const std::vector<const sim::Geant4Particle*>& cont,
0606                                           edm4hep::MCParticleCollection* coll)
0607     {
0608       /// Precreate objects to allow setting the references without second pass
0609       std::size_t i, n = cont.size();
0610       _pre_create(coll, n);
0611       /// Convert particle body
0612       for ( i=0; i<n; ++i)   {
0613         const auto* p = cont[i];
0614         auto  mcp = coll->at(i);
0615         _to_edm4hep(*p, mcp);
0616         /// Relationships are already resolved and kept in order: Just copy indices
0617         for (auto idau : p->daughters)
0618           mcp.addToDaughters(coll->at(idau));
0619         for (auto ipar : p->parents)
0620           mcp.addToParents(coll->at(ipar));
0621       }
0622     }
0623   }     // End namespace digi
0624 }       // End namespace dd4hep
0625 #endif  // DD4HEP_USE_DDG4 && DD4HEP_USE_EDM4HEP
0626 
0627 /// ======================================================================
0628 ///  Conversion from DDDigi in memory to edm4hep
0629 /// ======================================================================
0630 #ifdef DD4HEP_USE_EDM4HEP
0631 /// Namespace for the AIDA detector description toolkit
0632 namespace dd4hep {
0633 
0634   /// Namespace for the Digitization part of the AIDA detector description toolkit
0635   namespace digi {
0636 
0637     template <> template <> 
0638     void data_io<edm4hep_input>::_to_edm4hep(const ParticleMapping& cont,
0639                          edm4hep::MCParticleCollection* coll)
0640     {
0641       if ( cont.empty() )   {
0642         return;
0643       }
0644       else if ( _can_handle(edm4hep_input(), *cont.begin()) )  {
0645         auto vec = _to_vector(data_input<edm4hep_input>(), cont);
0646         if ( !vec.empty() )  {
0647       data_io<edm4hep_input>::_to_edm4hep(vec, coll);
0648         }
0649       }
0650       else if ( _can_handle(ddg4_input(), *cont.begin()) )  {
0651         auto vec = _to_vector(data_input<ddg4_input>(), cont);
0652         if ( !vec.empty() )  {
0653           data_io<ddg4_input>::_to_edm4hep(vec, coll);
0654         }
0655       }
0656       else   {
0657     // Catch-all: convert what we have at hands
0658     auto vec = _to_vector(data_input<digi_input>(), cont);
0659     if ( !vec.empty() )  {
0660       data_io<digi_input>::_to_edm4hep(vec, coll);
0661     }
0662       }
0663     }
0664   }     // End namespace digi
0665 }       // End namespace dd4hep
0666 #endif  // DD4HEP_USE_EDM4HEP