Back to home page

EIC code displayed by LXR

 
 

    


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

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