diff --git a/Simulation/ISF/ISF_Core/ISF_Event/ISF_Event/ISFTruthIncident.h b/Simulation/ISF/ISF_Core/ISF_Event/ISF_Event/ISFTruthIncident.h index 95c9c3996fbf51c98cf3197f00bfbb6d78b1a545..998c185d04107d2392058ba7d65427cc8fb35378 100644 --- a/Simulation/ISF/ISF_Core/ISF_Event/ISF_Event/ISFTruthIncident.h +++ b/Simulation/ISF/ISF_Core/ISF_Event/ISF_Event/ISFTruthIncident.h @@ -96,6 +96,11 @@ namespace ISF { simulation) - TODO only a dummy implementation currently */ virtual HepMC::GenParticlePtr updateChildParticle(unsigned short index, HepMC::GenParticlePtr existingChild) const override final; + /** Update the id and particleLink properties of the parentAfterIncident (to be called after registerTruthIncident) */ + void updateParentAfterIncidentProperties(); + /** Update the id and particleLink properties of the child particles (to be called after registerTruthIncident) */ + void updateChildParticleProperties(); + private: ISFTruthIncident(); diff --git a/Simulation/ISF/ISF_Core/ISF_Event/src/ISFTruthIncident.cxx b/Simulation/ISF/ISF_Core/ISF_Event/src/ISFTruthIncident.cxx index b7b31cf2686c9039b58a85336c05b092971f55d1..5fb1e9f75431fb1c088f7954e7d8c52e3c92de24 100644 --- a/Simulation/ISF/ISF_Core/ISF_Event/src/ISFTruthIncident.cxx +++ b/Simulation/ISF/ISF_Core/ISF_Event/src/ISFTruthIncident.cxx @@ -22,8 +22,9 @@ static HepMC::GenParticlePtr ParticleHelper_convert( const ISF::ISFParticle &par HepMC::FourVector fourMomentum( mom.x(), mom.y(), mom.z(), energy); auto hepParticle = HepMC::newGenParticlePtr( fourMomentum, particle.pdgCode(), particle.status() ); +#ifndef HEPMC3 HepMC::suggest_barcode(hepParticle, particle.barcode() ); - +#endif // return a newly created GenParticle return hepParticle; } @@ -119,6 +120,9 @@ HepMC::GenParticlePtr ISF::ISFTruthIncident::parentParticleAfterIncident(int new // set a new status m_parent.setStatus( parentStatus() + HepMC::SIM_STATUS_INCREMENT ); + // FIXME At this point the m_parent ISFParticle's id, truthBinding + // and particleLink all still need to be updated + // and update truth info (including the ISFParticle's HMPL) return updateHepMCTruthParticle(m_parent, &m_parent); } @@ -154,6 +158,12 @@ HepMC::GenParticlePtr ISF::ISFTruthIncident::childParticle(unsigned short index, sec->setBarcode( bc); } + // Enforce that the status is set correctly + sec->setStatus(1 + HepMC::SIM_STATUS_THRESHOLD); + + // FIXME At this point the sec ISFParticle's id, truthBinding + // and particleLink all still need to be updated + // and update truth info (including the ISFParticle's HMPL) return updateHepMCTruthParticle( *sec, &m_parent ); } @@ -171,7 +181,7 @@ HepMC::GenParticlePtr ISF::ISFTruthIncident::getHepMCTruthParticle( ISF::ISFPart HepMC::GenParticlePtr hepTruthParticle = truthBinding ? truthBinding->getTruthParticle() : nullptr; // We have what we want - if(hepTruthParticle){ + if (hepTruthParticle) { return hepTruthParticle; } //Otherwise we need to create it @@ -193,17 +203,81 @@ HepMC::GenParticlePtr ISF::ISFTruthIncident::updateHepMCTruthParticle( ISF::ISFP truthBinding = new TruthBinding( hepTruthParticle, hepPrimaryParticle, hepGenZeroParticle ); particle.setTruthBinding(truthBinding); } + // At this point the values returned by particle.getParticleLink() + // and particle.id() are not consistent with what is stored in the + // TruthBinding. - //register the new GenParticle as HepMcParticleLink, copying over some old properties if present - const HepMcParticleLink* oldHMPL = particle.getParticleLink(); - HepMcParticleLink* newHMPL = nullptr; - if (oldHMPL) { - newHMPL = new HepMcParticleLink(hepTruthParticle, oldHMPL->eventIndex(), HepMcParticleLink::IS_EVENTNUM); - delete oldHMPL; - } else { - newHMPL = new HepMcParticleLink(hepTruthParticle, 0, HepMcParticleLink::IS_EVENTNUM); // FIXME should be HepMcParticleLink::IS_POSITION + // FIXME Consider deleting the HepMcParticleLink and setting the id to HepMC::UNDEFINED_ID at this point? + return hepTruthParticle; +} + +/** Update the id and particleLink properties of the parentAfterIncident (to be called after registerTruthIncident) */ +void ISF::ISFTruthIncident::updateParentAfterIncidentProperties() { + // FIXME Check that we correctly deal with the case that the parent + // particle survives the interaction, but is rejected by + // registerTruthIncident + const ISF::TruthBinding *parentAfterIncidentTruthBinding = m_parent.getTruthBinding(); + auto parentAfterIncidentGenParticle = (parentAfterIncidentTruthBinding) ? parentAfterIncidentTruthBinding->getTruthParticle() : nullptr; + const int parentAfterIncidentID = (parentAfterIncidentGenParticle) ? HepMC::uniqueID(parentAfterIncidentGenParticle) : HepMC::UNDEFINED_ID; + HepMcParticleLink* parentAfterIncidentHMPL{}; + const HepMcParticleLink* parentBeforeIncidentHMPL = m_parent.getParticleLink(); + int eventIndex{0}; + if (parentAfterIncidentGenParticle) { eventIndex = parentAfterIncidentGenParticle->parent_event()->event_number(); } + else if (parentBeforeIncidentHMPL) { eventIndex = parentBeforeIncidentHMPL->eventIndex(); } + const HepMcParticleLink::PositionFlag idxFlag = + (eventIndex==0) ? HepMcParticleLink::IS_POSITION: HepMcParticleLink::IS_EVENTNUM; + if (parentBeforeIncidentHMPL) { + delete parentBeforeIncidentHMPL; + } + if (!parentAfterIncidentGenParticle) { + parentAfterIncidentHMPL = new HepMcParticleLink(parentAfterIncidentID, eventIndex, idxFlag, HepMcParticleLink::IS_ID); + } + else { + parentAfterIncidentHMPL = new HepMcParticleLink(parentAfterIncidentGenParticle, eventIndex, idxFlag); } - particle.setParticleLink(newHMPL); + m_parent.setId(parentAfterIncidentID); + m_parent.setParticleLink(parentAfterIncidentHMPL); +} - return hepTruthParticle; +/** Update the id and particleLink properties of the child particles (to be called after registerTruthIncident) */ +void ISF::ISFTruthIncident::updateChildParticleProperties() { + unsigned short numSec = numberOfChildren(); + for (unsigned short i=0; i<numSec; i++) { + // the current particle + ISF::ISFParticle *child = m_children[i]; + ISF::TruthBinding *childTruthBinding = child->getTruthBinding(); + if (!childTruthBinding) { + // Child particles which were rejected during + // registerTruthIncident need a TruthBinding + auto parentTruthBinding = m_parent.getTruthBinding(); + if (parentTruthBinding) { + childTruthBinding = parentTruthBinding->childTruthBinding(nullptr); + } + else { + // FIXME We really shouldn't end up here, possibly abort if we hit this? + childTruthBinding = new TruthBinding( nullptr, nullptr, nullptr ); + } + child->setTruthBinding(childTruthBinding); + } + auto childGenParticle = childTruthBinding->getTruthParticle(); + const int childID = (childGenParticle) ? HepMC::uniqueID(childGenParticle) : HepMC::UNDEFINED_ID; + HepMcParticleLink* childHMPL{}; + const HepMcParticleLink* oldChildHMPL = child->getParticleLink(); + int eventIndex{0}; + if (childGenParticle) { eventIndex = childGenParticle->parent_event()->event_number(); } + else if (oldChildHMPL) { eventIndex = oldChildHMPL->eventIndex(); } + const HepMcParticleLink::PositionFlag idxFlag = + (eventIndex==0) ? HepMcParticleLink::IS_POSITION: HepMcParticleLink::IS_EVENTNUM; + if (oldChildHMPL) { + delete oldChildHMPL; + } + if (!childGenParticle) { + childHMPL = new HepMcParticleLink(childID, eventIndex, idxFlag, HepMcParticleLink::IS_ID); + } + else { + childHMPL = new HepMcParticleLink(childGenParticle, eventIndex, idxFlag); + } + child->setId(childID); + child->setParticleLink(childHMPL); + } } diff --git a/Simulation/ISF/ISF_Core/ISF_Services/src/TruthSvc.cxx b/Simulation/ISF/ISF_Core/ISF_Services/src/TruthSvc.cxx index 2c63fcb7fd22737db4dfd697360d7516dd393892..d5d340ffe3719e056baa2b612d8cc83be783eb28 100644 --- a/Simulation/ISF/ISF_Core/ISF_Services/src/TruthSvc.cxx +++ b/Simulation/ISF/ISF_Core/ISF_Services/src/TruthSvc.cxx @@ -250,6 +250,9 @@ void ISF::TruthSvc::recordIncidentToMCTruth( ISF::ITruthIncident& ti, bool passW #ifdef HEPMC3 HepMC::suggest_barcode( parentAfterIncident, newPrimaryBC ); // TODO check this works correctly #endif + // NB For ISFTruthIncident the m_parent ISFParticle still needs + // its id and particleLink properties to be properly updated at + // this point. ATH_MSG_VERBOSE ( "Parent After Incident: " << parentAfterIncident << ", barcode: " << HepMC::barcode(parentAfterIncident)); } @@ -278,6 +281,9 @@ void ISF::TruthSvc::recordIncidentToMCTruth( ISF::ITruthIncident& ti, bool passW #ifdef HEPMC3 int secondaryParticleBCFromTI = ti.childBarcode(i); HepMC::suggest_barcode( p, secondaryParticleBCFromTI ? secondaryParticleBCFromTI : secondaryParticleBC ); + // NB For ISFTruthIncident the current child ISFParticle still needs + // its id and particleLink properties to be properly updated at + // this point. #endif } ATH_MSG_VERBOSE ( "Writing out " << i << "th child particle: " << p << ", barcode: " << HepMC::barcode(p)); diff --git a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimServices/src/FastCaloSimV2Tool.cxx b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimServices/src/FastCaloSimV2Tool.cxx index ebe953d79fa7f91ac3c40479dbf1f3da5409c08b..36ae8f140d5cfdbff27d30dbf010d755b765024b 100644 --- a/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimServices/src/FastCaloSimV2Tool.cxx +++ b/Simulation/ISF/ISF_FastCaloSim/ISF_FastCaloSimServices/src/FastCaloSimV2Tool.cxx @@ -226,6 +226,9 @@ StatusCode ISF::FastCaloSimV2Tool::simulate(ISF::ISFParticle& isfp, ISFParticleC ISF::fKillsPrimary); m_truthRecordSvc->registerTruthIncident( truth, true ); + // At this point we need to update the properties of the + // ISFParticles produced in the interaction + truth.updateChildParticleProperties(); for (auto *secondary : *someSecondaries) { if (secondary->getTruthBinding()) { diff --git a/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/HadIntProcessorParametric.cxx b/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/HadIntProcessorParametric.cxx index 1f93510737a2a68a61b16d9896d0a89381f1a9b2..5129f732bc3f420c2ac9da151118a2dca4406694 100644 --- a/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/HadIntProcessorParametric.cxx +++ b/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/HadIntProcessorParametric.cxx @@ -227,7 +227,7 @@ bool iFatras::HadIntProcessorParametric::hadronicInteraction(const Amg::Vector3D if (CLHEP::RandFlat::shoot(m_randomEngine) < (1. - prob) * m_hadIntProbScale ) return recordHadState(0.,p, position, momentum.unit(), - particle); + particle); // Registers TruthIncident internally // no hadronic interactions were computed return false; @@ -645,6 +645,9 @@ ISF::ISFParticleVector iFatras::HadIntProcessorParametric::getHadState(const ISF parent->nextGeoID(), ISF::fKillsPrimary ); m_truthRecordSvc->registerTruthIncident( truth); + // At this point we need to update the properties of the + // ISFParticles produced in the interaction + truth.updateChildParticleProperties(); // save info for validation if (m_validationMode && m_validationTool) { @@ -665,28 +668,29 @@ ISF::ISFParticleVector iFatras::HadIntProcessorParametric::getHadState(const ISF } bool iFatras::HadIntProcessorParametric::doHadronicInteraction(double time, const Amg::Vector3D& position, const Amg::Vector3D& momentum, - const Trk::Material* /*ematprop*/, - Trk::ParticleHypothesis particle, bool processSecondaries) const { + const Trk::Material* /*ematprop*/, + Trk::ParticleHypothesis particle, bool processSecondaries) const { + // Called by McMaterialEffectsUpdator::interact // get parent particle const ISF::ISFParticle *parent = ISF::ParticleClipboard::getInstance().getParticle(); // something is seriously wrong if there is no parent particle assert(parent); - ISF::ISFParticleVector ispVec=getHadState(parent, time, momentum.mag(), position, momentum.unit(), particle); + ISF::ISFParticleVector ispVec=getHadState(parent, time, momentum.mag(), position, momentum.unit(), particle); // Registers TruthIncident internally + // having no secondaries does not necessarily mean the interaction did not take place : TODO : add flag into ::getHadState // if (!ispVec.size()) return false; // push onto ParticleStack - if (processSecondaries && !ispVec.empty() ) { - // FIXME Check this doesn't cause problems in the TruthSvc - for (unsigned int ic=0; ic<ispVec.size(); ic++) { - if (!ispVec[ic]->getTruthBinding()) { - ispVec[ic]->setTruthBinding(new ISF::TruthBinding(*parent->getTruthBinding())); - } - m_particleBroker->push(ispVec[ic], parent); - } + for (auto *childParticle : ispVec) { + //Check that the new ISFParticles have a valid TruthBinding + if (!childParticle->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle); + } + m_particleBroker->push(childParticle, parent); + } } return true; @@ -697,8 +701,9 @@ ISF::ISFParticleVector iFatras::HadIntProcessorParametric::doHadIntOnLayer(const const Amg::Vector3D& position, const Amg::Vector3D& momentum, const Trk::Material* /*emat*/, Trk::ParticleHypothesis particle) const { - - return getHadState(parent, time, momentum.mag(), position, momentum.unit(), particle); + // called from McMaterialEffectsUpdator::interact and + // McMaterialEffectsUpdator::interactLay methods + return getHadState(parent, time, momentum.mag(), position, momentum.unit(), particle); // Registers TruthIncident internally } @@ -712,21 +717,21 @@ bool iFatras::HadIntProcessorParametric::recordHadState(double time, double p, // something is seriously wrong if there is no parent particle assert(parent); - ISF::ISFParticleVector ispVec=getHadState(parent, time, p, vertex, particleDir, particle); + ISF::ISFParticleVector ispVec=getHadState(parent, time, p, vertex, particleDir, particle); // Registers TruthIncident internally // having no secondaries does not necessarily mean the interaction did not take place : TODO : add flag into ::getHadState // if (!ispVec.size()) return false; // push onto ParticleStack if (!ispVec.empty() ) { - // FIXME Check this doesn't cause problems in the TruthSvc - for (unsigned int ic=0; ic<ispVec.size(); ic++) { - if (!ispVec[ic]->getTruthBinding()) { - ispVec[ic]->setTruthBinding(new ISF::TruthBinding(*parent->getTruthBinding())); - } - m_particleBroker->push(ispVec[ic], parent); - } -} + for (auto *childParticle : ispVec) { + //Check that the new ISFParticles have a valid TruthBinding + if (!childParticle->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle); + } + m_particleBroker->push(childParticle, parent); + } + } return true; } diff --git a/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/McMaterialEffectsUpdator.cxx b/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/McMaterialEffectsUpdator.cxx index ddd73064ce86507f3f9f3a99332d9ae6e4fdb926..81fe6bad991e6015c01516b5ccc264aafe05260a 100644 --- a/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/McMaterialEffectsUpdator.cxx +++ b/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/McMaterialEffectsUpdator.cxx @@ -492,6 +492,22 @@ iFatras::McMaterialEffectsUpdator::updateInLay( pathLim.updateMat(dX0, m_matProp->averageZ(), dInL0); // register particle if not in the stack already if (isp != m_isp) { + ISF::TruthBinding *regTruthBinding{}; + if (isp->getTruthBinding()) { + regTruthBinding = new ISF::TruthBinding(*(isp->getTruthBinding())); + } + else { + ATH_MSG_WARNING("Incomming ISParticle had no TruthBinding " << *isp); + regTruthBinding = new ISF::TruthBinding(nullptr, nullptr, nullptr); + } + HepMcParticleLink *regHMPL{}; + if (isp->getParticleLink()) { + regHMPL = new HepMcParticleLink(*(isp->getParticleLink())); + } + else { + ATH_MSG_WARNING("Incomming ISParticle had no ParticleLink: " << *isp); + regHMPL = new HepMcParticleLink(isp->id(), 0, HepMcParticleLink::IS_POSITION, HepMcParticleLink::IS_ID); + } ISF::ISFParticle* regisp = new ISF::ISFParticle(isp->position(), currPar->momentum(), isp->mass(), @@ -501,7 +517,9 @@ iFatras::McMaterialEffectsUpdator::updateInLay( isp->timeStamp(), *m_isp, isp->id(), - isp->barcode() // FIXME barcode-based + isp->barcode(), // FIXME barcode-based + regTruthBinding, + regHMPL ); // add presampled process info if (isp->getUserInformation() && isp->getUserInformation()->materialLimit()) { @@ -530,10 +548,10 @@ iFatras::McMaterialEffectsUpdator::updateInLay( } regisp->setUserInformation(validInfo); } - // Making sure we get some correct truth info from parent if needed + // Check that the returned ISFParticle has a valid TruthBinding // before pushing into the particle broker if (!regisp->getTruthBinding()) { - regisp->setTruthBinding(new ISF::TruthBinding(*isp->getTruthBinding())); + ATH_MSG_ERROR("Could not retrieve TruthBinding from non-interacting ISFParticle "<< *regisp); } m_particleBroker->push(regisp, m_isp); } @@ -629,7 +647,7 @@ iFatras::McMaterialEffectsUpdator::updateInLay( ISF::ISFParticleVector childs; if (iStatus == 1) { - childs = interactLay(isp, timeLim.time, *currPar, particle, pathLim.process); + childs = interactLay(isp, timeLim.time, *currPar, particle, pathLim.process); // Registers TruthIncident internally } else { if (extMatProp) { childs = m_hadIntProcessor->doHadIntOnLayer( @@ -683,6 +701,22 @@ iFatras::McMaterialEffectsUpdator::updateInLay( // register particle if not in the stack already if (isp != m_isp) { + ISF::TruthBinding *regTruthBinding{}; + if (isp->getTruthBinding()) { + regTruthBinding = new ISF::TruthBinding(*(isp->getTruthBinding())); + } + else { + ATH_MSG_WARNING("Incomming ISParticle had no TruthBinding " << *isp); + regTruthBinding = new ISF::TruthBinding(nullptr, nullptr, nullptr); + } + HepMcParticleLink *regHMPL{}; + if (isp->getParticleLink()) { + regHMPL = new HepMcParticleLink(*(isp->getParticleLink())); + } + else { + ATH_MSG_WARNING("Incomming ISParticle had no ParticleLink: " << *isp); + regHMPL = new HepMcParticleLink(isp->id(), 0, HepMcParticleLink::IS_POSITION, HepMcParticleLink::IS_ID); + } ISF::ISFParticle* regisp = new ISF::ISFParticle(isp->position(), currPar->momentum(), isp->mass(), @@ -692,7 +726,9 @@ iFatras::McMaterialEffectsUpdator::updateInLay( isp->timeStamp(), *m_isp, isp->id(), - isp->barcode() // FIXME barcode-based + isp->barcode(), // FIXME barcode-based + regTruthBinding, + regHMPL ); // add presampled process info if (isp->getUserInformation() && isp->getUserInformation()->materialLimit()) { @@ -718,9 +754,10 @@ iFatras::McMaterialEffectsUpdator::updateInLay( else validInfo->setGeneration(-1); // signal problem in the validation chain } - // Making sure we get some correct truth info from parent if needed before pushing into the particle broker + // Check that the returned ISFParticle has a valid TruthBinding + // before pushing into the particle broker if (!regisp->getTruthBinding()) { - regisp->setTruthBinding(new ISF::TruthBinding(*isp->getTruthBinding())); + ATH_MSG_ERROR("Could not retrieve TruthBinding from non-interacting ISFParticle "<< *regisp); } m_particleBroker->push(regisp, m_isp); } @@ -1316,12 +1353,21 @@ void iFatras::McMaterialEffectsUpdator::recordBremPhoton(double time, parent->nextGeoID(), ISF::fPrimarySurvives ); m_truthRecordSvc->registerTruthIncident( truth); - //Making sure we get some correct truth info from parent if needed before pushing into the particle broker - if (!bremPhoton->getTruthBinding()) { - bremPhoton->setTruthBinding(new ISF::TruthBinding(*parent->getTruthBinding())); + // At this point we need to update the properties of the + // ISFParticles produced in the interaction + truth.updateParentAfterIncidentProperties(); + truth.updateChildParticleProperties(); + + // Check that the new/updated ISFParticles have a valid TruthBinding before pushing into the particle broker + if (!parent->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from parent ISFParticle "<< *parent); + } + for (auto *childParticle : children) { + if (!childParticle->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle); + } + m_particleBroker->push(childParticle, parent); } - m_particleBroker->push( bremPhoton, parent); - // save info for validation if (m_validationMode && m_validationTool) { @@ -1449,10 +1495,19 @@ void iFatras::McMaterialEffectsUpdator::recordBremPhotonLay(const ISF::ISFPartic parent->nextGeoID(), ISF::fPrimarySurvives ); m_truthRecordSvc->registerTruthIncident( truth); - - //Making sure we get some correct truth info from parent if needed before pushing into the particle broker - if (!bremPhoton->getTruthBinding()) { - bremPhoton->setTruthBinding(new ISF::TruthBinding(*parent->getTruthBinding())); + // At this point we need to update the properties of the + // ISFParticles produced in the interaction + truth.updateParentAfterIncidentProperties(); + truth.updateChildParticleProperties(); + + // Check that the new/updated ISFParticles have a valid TruthBinding + if (!parent->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from parent ISFParticle "<< *parent); + } + for (auto *childParticle : children) { + if (!childParticle->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle); + } } // save info for validation @@ -1537,6 +1592,7 @@ iFatras::McMaterialEffectsUpdator::interact(double time, int process, const Trk::Material* extMatProp) const { + // Responsible for registering TruthIncidents if (process == 0) return nullptr; @@ -1554,13 +1610,24 @@ iFatras::McMaterialEffectsUpdator::interact(double time, // update parent before decay ISF::ISFParticleVector childVector = m_particleDecayer->decayParticle(*parent,position,momentum,time); - for (unsigned int i=0; i<childVector.size(); i++) { + // register TruthIncident + ISF::ISFTruthIncident truth( const_cast<ISF::ISFParticle&>(*parent), + childVector, + process, + parent->nextGeoID(), // inherits from the parent + ISF::fKillsPrimary ); + m_truthRecordSvc->registerTruthIncident( truth); + // At this point we need to update the properties of the + // ISFParticles produced in the interaction + truth.updateChildParticleProperties(); + + for (unsigned int i=0; i<childVector.size(); i++) { // in the validation mode, add process info if (m_validationMode) { - ISF::ParticleUserInformation* validInfo = new ISF::ParticleUserInformation(); - validInfo->setProcess(process); - if (parent->getUserInformation()) validInfo->setGeneration(parent->getUserInformation()->generation()+1); - else validInfo->setGeneration(1); // assume parent is a primary track + ISF::ParticleUserInformation* validInfo = new ISF::ParticleUserInformation(); + validInfo->setProcess(process); + if (parent->getUserInformation()) validInfo->setGeneration(parent->getUserInformation()->generation()+1); + else validInfo->setGeneration(1); // assume parent is a primary track childVector[i]->setUserInformation(validInfo); } // register next geo (is current), next flavor can be defined by filter @@ -1569,14 +1636,6 @@ iFatras::McMaterialEffectsUpdator::interact(double time, m_particleBroker->push(childVector[i], parent); } - // register TruthIncident - ISF::ISFTruthIncident truth( const_cast<ISF::ISFParticle&>(*parent), - childVector, - process, - parent->nextGeoID(), // inherits from the parent - ISF::fKillsPrimary ); - m_truthRecordSvc->registerTruthIncident( truth); - // save info for validation if (m_validationMode && m_validationTool) { Amg::Vector3D* nMom = nullptr; @@ -1623,6 +1682,28 @@ iFatras::McMaterialEffectsUpdator::interact(double time, id ); + // register TruthIncident + ISF::ISFTruthIncident truth( const_cast<ISF::ISFParticle&>(*parent), + children, + process, + parent->nextGeoID(), // inherits from the parent + ISF::fPrimarySurvives ); + m_truthRecordSvc->registerTruthIncident( truth); + // At this point we need to update the properties of the + // ISFParticles produced in the interaction + truth.updateParentAfterIncidentProperties(); + truth.updateChildParticleProperties(); + + // Check that the new/updated ISFParticles have a valid TruthBinding + if (!parent->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from parent ISFParticle "<< *parent); + } + for (auto *childParticle : children) { + if (!childParticle->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle); + } + } + // in the validation mode, add process info if (m_validationMode) { ISF::ParticleUserInformation* validInfo1 = new ISF::ParticleUserInformation(); @@ -1637,14 +1718,6 @@ iFatras::McMaterialEffectsUpdator::interact(double time, children[1]->setUserInformation(validInfo2); } - // register TruthIncident - ISF::ISFTruthIncident truth( const_cast<ISF::ISFParticle&>(*parent), - children, - process, - parent->nextGeoID(), // inherits from the parent - ISF::fPrimarySurvives ); - m_truthRecordSvc->registerTruthIncident( truth); - // push child particles onto stack m_particleBroker->push( children[0], parent); m_particleBroker->push( children[1], parent); @@ -1664,12 +1737,12 @@ iFatras::McMaterialEffectsUpdator::interact(double time, auto parm = std::make_unique<Trk::NeutralCurvilinearParameters>(position,momentum,parent->charge()); - bool cStat = m_conversionTool->doConversion(time, *parm); + bool cStat = m_conversionTool->doConversion(time, *parm); // Registers TruthIncident internally if (!cStat) ATH_MSG_WARNING( "Conversion failed, killing photon anyway "); // kill the mother particle - return nullptr; + return nullptr; } if (process==121) { // hadronic interaction @@ -1678,7 +1751,7 @@ iFatras::McMaterialEffectsUpdator::interact(double time, auto parm = std::make_unique<Trk::CurvilinearParameters>(position,momentum,parent->charge()); - bool recHad = m_hadIntProcessor->doHadronicInteraction(time, position, momentum, extMatProp, particle, true); + bool recHad = m_hadIntProcessor->doHadronicInteraction(time, position, momentum, extMatProp, particle, true); // Registers TruthIncident internally // eventually : bool recHad = m_hadIntProcessor->recordHadState( time, p, position, pDir, particle); // kill the track if interaction recorded -------------------------- @@ -1693,11 +1766,11 @@ iFatras::McMaterialEffectsUpdator::interact(double time, } ISF::ISFParticleVector iFatras::McMaterialEffectsUpdator::interactLay(const ISF::ISFParticle* parent, - double time, - const Trk::TrackParameters& parm, - Trk::ParticleHypothesis particle, - int process, - const Trk::MaterialProperties* extMatProp) const { + double time, + const Trk::TrackParameters& parm, + Trk::ParticleHypothesis particle, + int process, + const Trk::MaterialProperties* extMatProp) const { ISF::ISFParticleVector childVector(0); if ( process==0 ) return childVector; @@ -1765,6 +1838,10 @@ ISF::ISFParticleVector iFatras::McMaterialEffectsUpdator::interactLay(const ISF parent->nextGeoID(), // inherits from the parent ISF::fPrimarySurvives ); m_truthRecordSvc->registerTruthIncident( truth); + // At this point we need to update the properties of the + // ISFParticles produced in the interaction + truth.updateParentAfterIncidentProperties(); + truth.updateChildParticleProperties(); // save info for validation if (m_validationMode && m_validationTool) { @@ -1773,12 +1850,14 @@ ISF::ISFParticleVector iFatras::McMaterialEffectsUpdator::interactLay(const ISF delete nMom; } - //Making sure we get some correct truth info from parent if needed before pushing into the particle broker - if (!children[0]->getTruthBinding()) { - children[0]->setTruthBinding(new ISF::TruthBinding(*parent->getTruthBinding())); + // Check that the new/updated ISFParticles have a valid TruthBinding + if (!parent->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from parent ISFParticle "<< *parent); } - if (!children[1]->getTruthBinding()) { - children[1]->setTruthBinding(new ISF::TruthBinding(*parent->getTruthBinding())); + for (auto *childParticle : children) { + if (!childParticle->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle); + } } return children; @@ -1787,32 +1866,32 @@ ISF::ISFParticleVector iFatras::McMaterialEffectsUpdator::interactLay(const ISF if (process==14) { // photon conversion Trk::NeutralCurvilinearParameters neu(position,momentum,parent->charge()); - childVector=m_conversionTool->doConversionOnLayer(parent, time, neu); + childVector=m_conversionTool->doConversionOnLayer(parent, time, neu); // Registers TruthIncident internally // validation mode if (m_validationMode && m_validationTool) { // add process info for children for (unsigned int i=0; i<childVector.size(); i++) { - ISF::ParticleUserInformation* validInfo = new ISF::ParticleUserInformation(); - validInfo->setProcess(process); - if (parent->getUserInformation()) validInfo->setGeneration(parent->getUserInformation()->generation()+1); - else validInfo->setGeneration(1); // assume parent is a primary track - childVector[i]->setUserInformation(validInfo); + ISF::ParticleUserInformation* validInfo = new ISF::ParticleUserInformation(); + validInfo->setProcess(process); + if (parent->getUserInformation()) validInfo->setGeneration(parent->getUserInformation()->generation()+1); + else validInfo->setGeneration(1); // assume parent is a primary track + childVector[i]->setUserInformation(validInfo); } // save interaction info if ( m_validationTool ) { - Amg::Vector3D* nMom = nullptr; - m_validationTool->saveISFVertexInfo(process, position,*parent,momentum,nMom,childVector); - delete nMom; + Amg::Vector3D* nMom = nullptr; + m_validationTool->saveISFVertexInfo(process, position,*parent,momentum,nMom,childVector); + delete nMom; } } - //Making sure we get some correct truth info from parent if needed before pushing into the particle broker - for (unsigned int i=0; i<childVector.size(); i++) { - if (!childVector[i]->getTruthBinding()) { - childVector[i]->setTruthBinding(new ISF::TruthBinding(*parent->getTruthBinding())); - } + // Check that the new ISFParticles have a valid TruthBinding + for (auto *childParticle : childVector) { + if (!childParticle->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle); + } } return childVector; @@ -1821,7 +1900,7 @@ ISF::ISFParticleVector iFatras::McMaterialEffectsUpdator::interactLay(const ISF if (process==121) { // hadronic interaction return ( m_hadIntProcessor->doHadIntOnLayer(parent, time, position, momentum, - extMatProp? &extMatProp->material() : nullptr, particle) ); + extMatProp? &extMatProp->material() : nullptr, particle) ); } @@ -1830,10 +1909,10 @@ ISF::ISFParticleVector iFatras::McMaterialEffectsUpdator::interactLay(const ISF // in the validation mode, add process info if (m_validationMode) { for (unsigned int i=0; i<childVector.size(); i++) { - ISF::ParticleUserInformation* validInfo = new ISF::ParticleUserInformation(); - validInfo->setProcess(process); - if (parent->getUserInformation()) validInfo->setGeneration(parent->getUserInformation()->generation()+1); - else validInfo->setGeneration(1); // assume parent is a primary track + ISF::ParticleUserInformation* validInfo = new ISF::ParticleUserInformation(); + validInfo->setProcess(process); + if (parent->getUserInformation()) validInfo->setGeneration(parent->getUserInformation()->generation()+1); + else validInfo->setGeneration(1); // assume parent is a primary track childVector[i]->setUserInformation(validInfo); } } @@ -1845,6 +1924,9 @@ ISF::ISFParticleVector iFatras::McMaterialEffectsUpdator::interactLay(const ISF parent->nextGeoID(), // inherits from the parent ISF::fKillsPrimary ); m_truthRecordSvc->registerTruthIncident( truth); + // At this point we need to update the properties of the + // ISFParticles produced in the interaction + truth.updateChildParticleProperties(); // save info for validation if (m_validationMode && m_validationTool) { @@ -1854,11 +1936,11 @@ ISF::ISFParticleVector iFatras::McMaterialEffectsUpdator::interactLay(const ISF } } - //Making sure we get some correct truth info from parent if needed before pushing into the particle broker - for (unsigned int i=0; i<childVector.size(); i++) { - if (!childVector[i]->getTruthBinding()) { - childVector[i]->setTruthBinding(new ISF::TruthBinding(*parent->getTruthBinding())); - } + // Check that the new ISFParticles have a valid TruthBinding + for (auto *childParticle : childVector) { + if (!childParticle->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle); + } } return childVector; diff --git a/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/PhotonConversionTool.cxx b/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/PhotonConversionTool.cxx index 528ad9ca62150995491b2a6bb27072f1dc716773..be5a1c512444307a170388afe1aa08404bab01f8 100755 --- a/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/PhotonConversionTool.cxx +++ b/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/PhotonConversionTool.cxx @@ -264,11 +264,6 @@ void iFatras::PhotonConversionTool::recordChilds(double time, ch1->setUserInformation(validInfo); } children[ichild] = ch1; - // FIXME Check this doesn't cause problems in the TruthSvc - if (!ch1->getTruthBinding()) { - ch1->setTruthBinding(new ISF::TruthBinding(*parent->getTruthBinding())); - } - m_particleBroker->push( ch1, parent); ichild++; } @@ -293,11 +288,6 @@ void iFatras::PhotonConversionTool::recordChilds(double time, ch2->setUserInformation(validInfo); } children[ichild] = ch2; - // FIXME Check this doesn't cause problems in the TruthSvc - if (!ch2->getTruthBinding()) { - ch2->setTruthBinding(new ISF::TruthBinding(*parent->getTruthBinding())); - } - m_particleBroker->push( ch2, parent); } // register TruthIncident @@ -307,6 +297,20 @@ void iFatras::PhotonConversionTool::recordChilds(double time, parent->nextGeoID(), ISF::fKillsPrimary ); m_truthRecordSvc->registerTruthIncident( truth); + // At this point we need to update the properties of the + // ISFParticles produced in the interaction + truth.updateChildParticleProperties(); + + // push onto ParticleStack + if (!children.empty() ) { + for (auto *childParticle : children) { + //Check that the new ISFParticles have a valid TruthBinding + if (!childParticle->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle); + } + m_particleBroker->push(childParticle, parent); + } + } // save info for validation if (m_validationMode && m_validationTool) { @@ -324,6 +328,7 @@ ISF::ISFParticleVector iFatras::PhotonConversionTool::getChilds(const ISF::ISFPa const Amg::Vector3D& childDirection, Trk::ParticleHypothesis childType) const { + // Called by PhotonConversionTool::doConversionOnLayer // calculate the child momentum double p1 = sqrt(childEnergy*childEnergy-Trk::ParticleMasses::mass[childType]*Trk::ParticleMasses::mass[childType]); @@ -388,14 +393,15 @@ ISF::ISFParticleVector iFatras::PhotonConversionTool::getChilds(const ISF::ISFPa parent->nextGeoID(), ISF::fKillsPrimary ); m_truthRecordSvc->registerTruthIncident( truth); - - //Make sure the conversion products get a chance to have correct truth info before pushing into the particle broker - // FIXME Check this doesn't cause problems later in the TruthSvc - if (!children[0]->getTruthBinding()) { - children[0]->setTruthBinding(new ISF::TruthBinding(*parent->getTruthBinding())); - } - if (!children[1]->getTruthBinding()) { - children[1]->setTruthBinding(new ISF::TruthBinding(*parent->getTruthBinding())); + // At this point we need to update the properties of the + // ISFParticles produced in the interaction + truth.updateChildParticleProperties(); + + // Check that the new ISFParticles have a valid TruthBinding + for (auto *childParticle : children) { + if (!childParticle->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle); + } } return children; @@ -613,6 +619,7 @@ Amg::Vector3D iFatras::PhotonConversionTool::childDirection(const Amg::Vector3D& bool iFatras::PhotonConversionTool::doConversion(double time, const Trk::NeutralParameters& parm, const Trk::ExtendedMaterialProperties* /*extMatProp*/) const { + // Called by McMaterialEffectsUpdator::interact double p = parm.momentum().mag(); // get the energy @@ -632,7 +639,7 @@ bool iFatras::PhotonConversionTool::doConversion(double time, const Trk::Neutral parm.momentum().unit(), childEnergy, p, childDir, - Trk::electron); + Trk::electron); // Registers TruthIncident internally // fill the TTree ---------------------------- if (m_validationTree) m_validationTree->Fill(); @@ -644,7 +651,7 @@ bool iFatras::PhotonConversionTool::doConversion(double time, const Trk::Neutral ISF::ISFParticleVector iFatras::PhotonConversionTool::doConversionOnLayer(const ISF::ISFParticle* parent, double time, const Trk::NeutralParameters& parm, const Trk::ExtendedMaterialProperties* /*ematprop*/) const { - + // Called by McMaterialEffectsUpdator::interactLay double p = parm.momentum().mag(); // get the energy @@ -668,7 +675,7 @@ ISF::ISFParticleVector iFatras::PhotonConversionTool::doConversionOnLayer(const parm.momentum().unit(), childEnergy, p, childDir, - Trk::electron); + Trk::electron); // Registers TruthIncident internally } diff --git a/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/TransportTool.cxx b/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/TransportTool.cxx index 9a517fe89023c89c52d90a46c5ec588a4e5321b6..7b097a056460714416d37c20be1dd9423e7a515e 100755 --- a/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/TransportTool.cxx +++ b/Simulation/ISF/ISF_Fatras/ISF_FatrasTools/src/TransportTool.cxx @@ -243,7 +243,7 @@ ISF::ISFParticle* iFatras::TransportTool::process( const ISF::ISFParticle& isp, if ( freepath>0. && freepath<0.01 ) { if (!m_particleDecayHelper.empty()) { ATH_MSG_VERBOSE( "[ fatras transport ] Decay is triggered for input particle."); - m_particleDecayHelper->decay(isp,isp.position(),isp.momentum(),isp.timeStamp()); + m_particleDecayHelper->decay(isp,isp.position(),isp.momentum(),isp.timeStamp()); // Registers TruthIncident internally } // validation mode - for all particle registered into stack @@ -381,7 +381,7 @@ ISF::ISFParticle* iFatras::TransportTool::process( const ISF::ISFParticle& isp, if (uisp && timeLim.tMax>0. && timeLim.time >=timeLim.tMax ) { if (!m_particleDecayHelper.empty()) { ATH_MSG_VERBOSE( "[ fatras transport ] Decay is triggered for input particle."); - m_particleDecayHelper->decay(*uisp,uisp->position(),uisp->momentum(),uisp->timeStamp()); + m_particleDecayHelper->decay(*uisp,uisp->position(),uisp->momentum(),uisp->timeStamp()); // Registers TruthIncident internally } delete uisp; return nullptr; diff --git a/Simulation/ISF/ISF_Fatras/ISF_FatrasToolsG4/src/G4HadIntProcessor.cxx b/Simulation/ISF/ISF_Fatras/ISF_FatrasToolsG4/src/G4HadIntProcessor.cxx index 2dc8db93d025d11137c2f03ce32cfa990f621928..6e8d1c20ecae56bce40c4d6661205634b1496025 100644 --- a/Simulation/ISF/ISF_Fatras/ISF_FatrasToolsG4/src/G4HadIntProcessor.cxx +++ b/Simulation/ISF/ISF_Fatras/ISF_FatrasToolsG4/src/G4HadIntProcessor.cxx @@ -495,16 +495,6 @@ ISF::ISFParticleVector iFatras::G4HadIntProcessor::getHadState(const ISF::ISFPar const G4ThreeVector &momG4 = dynPar->GetMomentum(); Amg::Vector3D mom( momG4.x(), momG4.y(), momG4.z() ); - //Let's make sure the new ISFParticles get a valid TruthBinding - // FIXME check that this does not cause problems in the TruthSvc - ISF::TruthBinding* truthBinding{}; - if (parent->getTruthBinding()) { - ATH_MSG_VERBOSE("Could retrieve TruthBinding from original ISFParticle"); - truthBinding = new ISF::TruthBinding(*parent->getTruthBinding()); - } - else { - ATH_MSG_WARNING("Could not retrieve TruthBinding from original ISFParticle, might cause issues later on."); - } const int status = 1 + HepMC::SIM_STATUS_THRESHOLD; const int id = HepMC::UNDEFINED_ID; ISF::ISFParticle* cParticle = new ISF::ISFParticle( position, @@ -515,9 +505,7 @@ ISF::ISFParticleVector iFatras::G4HadIntProcessor::getHadState(const ISF::ISFPar status, time, *parent, - id, - HepMC::UNDEFINED_ID, // barcode - truthBinding ); + id ); cParticle->setNextGeoID( parent->nextGeoID() ); cParticle->setNextSimID( parent->nextSimID() ); // process sampling tool takes care of validation info @@ -526,7 +514,25 @@ ISF::ISFParticleVector iFatras::G4HadIntProcessor::getHadState(const ISF::ISFPar } children.resize(numChildren); - // truth info handled by process sampling tool + + // register TruthIncident + const int processForTI = 121; // Hadronic interaction + ISF::ISFTruthIncident truth( const_cast<ISF::ISFParticle&>(*parent), + children, + processForTI, + parent->nextGeoID(), // inherits from the parent + ISF::fKillsPrimary ); + m_truthRecordSvc->registerTruthIncident( truth); + // At this point we need to update the properties of the + // ISFParticles produced in the interaction + truth.updateChildParticleProperties(); + + // Check that the new ISFParticles have a valid TruthBinding + for (auto *childParticle : children) { + if (!childParticle->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle); + } + } // free up memory g4change->Clear(); @@ -546,25 +552,25 @@ bool iFatras::G4HadIntProcessor::doHadronicInteraction(double time, const Amg::V Trk::ParticleHypothesis /*particle*/, bool processSecondaries) const { + // Called by G4HadIntProcessor::hadronicInteraction and McMaterialEffectsUpdator::interact // get parent particle // @TODO: replace by Fatras internal bookkeeping const ISF::ISFParticle *parent = ISF::ParticleClipboard::getInstance().getParticle(); // something is seriously wrong if there is no parent particle assert(parent); - ISF::ISFParticleVector ispVec=getHadState(parent, time, position, momentum, ematprop); + ISF::ISFParticleVector ispVec=getHadState(parent, time, position, momentum, ematprop); // Registers TruthIncident interally - if (!ispVec.size()) return false; + if (ispVec.empty()) return false; // FIXME Inconsistent with HadIntProcessorParametric::doHadronicInteraction // push onto ParticleStack - if (processSecondaries) { - for (unsigned int ic=0; ic<ispVec.size(); ic++) { - //First let's make sure that new ISFParticles have valid truth info - if (!ispVec[ic]->getTruthBinding()) { - ispVec[ic]->setTruthBinding(new ISF::TruthBinding(*parent->getTruthBinding())); - } - m_particleBroker->push(ispVec[ic], parent); + for (auto *childParticle : ispVec) { + //Check that the new ISFParticles have a valid TruthBinding + if (!childParticle->getTruthBinding()) { + ATH_MSG_ERROR("Could not retrieve TruthBinding from child ISFParticle "<< *childParticle); + } + m_particleBroker->push(childParticle, parent); } } @@ -578,7 +584,7 @@ ISF::ISFParticleVector iFatras::G4HadIntProcessor::doHadIntOnLayer(const ISF::IS Trk::ParticleHypothesis /*particle=Trk::pion*/) const { - return getHadState(parent, time, position, momentum, emat); + return getHadState(parent, time, position, momentum, emat); // Registers TruthIncident interally } diff --git a/Simulation/ISF/ISF_Fatras/ISF_FatrasToolsG4/src/G4ParticleDecayHelper.cxx b/Simulation/ISF/ISF_Fatras/ISF_FatrasToolsG4/src/G4ParticleDecayHelper.cxx index ca606257cab89078c2faed019c988329ec6695c4..6e11f6076282be539c4c48d17cc9e9cc58dc62ac 100644 --- a/Simulation/ISF/ISF_Fatras/ISF_FatrasToolsG4/src/G4ParticleDecayHelper.cxx +++ b/Simulation/ISF/ISF_Fatras/ISF_FatrasToolsG4/src/G4ParticleDecayHelper.cxx @@ -206,62 +206,65 @@ void iFatras::G4ParticleDecayHelper::decay(const ISF::ISFParticle& particleToDec const ISF::ISFParticleVector decayProducts = decayParticle(particleToDecay,vertex,momentum,timeStamp); // fill them into broker & truth svc - handleDecayParticles(particleToDecay,decayProducts); + handleDecayParticles(particleToDecay,decayProducts); // Registers TruthIncident internally } - + void iFatras::G4ParticleDecayHelper::handleDecayParticles(const ISF::ISFParticle& particle, const ISF::ISFParticleVector& decayProducts) const { // process the decay products --------------------------------------- int process = 201; - // (i) none + + // (i) none if (!decayProducts.size()) { ATH_MSG_WARNING("[ decay ] Particle Decay Creator did not return any" << " decay products for particle with PDG code " - << particle.pdgCode() ); + << particle.pdgCode() ); } else { // (ii) many std::ostringstream productSummaryString; productSummaryString << "[ decay ] products:"; - //!< @TODO - // truth service !!! - // simulate the tracks of the daughter particles ------- run over decay products - - ISF::ISFParticleVector::const_iterator decayProductsItr = decayProducts.begin(); - for (; decayProductsItr != decayProducts.end(); ++decayProductsItr) - { - productSummaryString << " - " << (**decayProductsItr) << '\n'; - // in the validation mode, add process info - if (m_validationMode) { - ISF::ParticleUserInformation* validInfo = new ISF::ParticleUserInformation(); - validInfo->setProcess(process); - if (particle.getUserInformation()) validInfo->setGeneration(particle.getUserInformation()->generation()+1); - else validInfo->setGeneration(1); // assume parent is a primary track - (*decayProductsItr)->setUserInformation(validInfo); - } - // register next geo (is current), next flavor can be defined by filter - (*decayProductsItr)->setNextGeoID( particle.nextGeoID() ); - // feed it the particle broker with parent information - m_particleBroker->push(*decayProductsItr, &particle); + + for (ISF::ISFParticle *decayProduct : decayProducts) { + productSummaryString << " - " << (*decayProduct) << '\n'; + // in the validation mode, add process info + if (m_validationMode) { + ISF::ParticleUserInformation* validInfo = new ISF::ParticleUserInformation(); + validInfo->setProcess(process); + if (particle.getUserInformation()) validInfo->setGeneration(particle.getUserInformation()->generation()+1); + else validInfo->setGeneration(1); // assume parent is a primary track + decayProduct->setUserInformation(validInfo); + } + // register next geo (is current), next flavor can be defined by filter + decayProduct->setNextGeoID( particle.nextGeoID() ); }//loop over all decay products - ATH_MSG_VERBOSE( productSummaryString.str() ); // register TruthIncident ISF::ISFTruthIncident truth( const_cast<ISF::ISFParticle&>(particle), - decayProducts, - process, - particle.nextGeoID(), // inherits from the parent - ISF::fKillsPrimary ); + decayProducts, + process, + particle.nextGeoID(), // inherits from the parent + ISF::fKillsPrimary ); m_truthRecordSvc->registerTruthIncident( truth); - + // At this point we need to update the properties of the + // ISFParticles produced in the interaction + truth.updateChildParticleProperties(); + + // simulate the tracks of the daughter particles ------- run over decay products + for (ISF::ISFParticle *decayProduct : decayProducts) { + // feed it the particle broker with parent information + m_particleBroker->push(decayProduct, &particle); + }//loop over all decay products + ATH_MSG_VERBOSE( productSummaryString.str() ); + // save info for validation if (m_validationMode && m_validationTool) { - Amg::Vector3D* nMom = 0; - m_validationTool->saveISFVertexInfo(process,particle.position(),particle,particle.momentum(),nMom,decayProducts); - delete nMom; + Amg::Vector3D* nMom = 0; + m_validationTool->saveISFVertexInfo(process,particle.position(),particle,particle.momentum(),nMom,decayProducts); + delete nMom; } - } + } } std::vector<ISF::ISFParticle*> @@ -270,6 +273,7 @@ iFatras::G4ParticleDecayHelper::decayParticle(const ISF::ISFParticle& parent, const Amg::Vector3D& momentum, double timeStamp) const { + // Called from McMaterialEffectsUpdator::interact, McMaterialEffectsUpdator::interactLay and G4ParticleDecayHelper::decay // return vector for children std::vector<ISF::ISFParticle*> children; @@ -368,14 +372,6 @@ iFatras::G4ParticleDecayHelper::decayParticle(const ISF::ISFParticle& parent, const G4ThreeVector &mom= prod->GetMomentum(); Amg::Vector3D amgMom( mom.x(), mom.y(), mom.z() ); - //Let's make sure the new ISFParticles get a valid TruthBinding - // FIXME check that this does not cause problems in the TruthSvc - ISF::TruthBinding* truthBinding{}; - if (parent.getTruthBinding()) { - ATH_MSG_VERBOSE("Could retrieve TruthBinding from original ISFParticle"); - truthBinding = new ISF::TruthBinding(*parent.getTruthBinding()); - } - else { ATH_MSG_WARNING("Could not retrieve original TruthBinding from ISFParticle"); } const int status = 1 + HepMC::SIM_STATUS_THRESHOLD; const int id = HepMC::UNDEFINED_ID; ISF::ISFParticle* childParticle = new ISF::ISFParticle( vertex, @@ -386,9 +382,7 @@ iFatras::G4ParticleDecayHelper::decayParticle(const ISF::ISFParticle& parent, status, timeStamp, parent, - id, - HepMC::UNDEFINED_ID, // barcode - truthBinding ); + id ); children.push_back( childParticle); }