Print matching information in a provided validation info object, and write information to tree if configured to do so.
96 if (printToScreen && useInterpretedMatching)
97 std::cout <<
"---INTERPRETED-MATCHING-OUTPUT------------------------------------------------------------------" << std::endl;
98 else if (printToScreen)
99 std::cout <<
"---RAW-MATCHING-OUTPUT--------------------------------------------------------------------------" << std::endl;
102 useInterpretedMatching ? validationInfo.GetInterpretedMCToPfoHitSharingMap() : validationInfo.GetMCToPfoHitSharingMap());
108 PfoVector primaryPfoVector;
111 int pfoIndex(0), testBeamPfoIndex(0);
114 for (
const Pfo *
const pPrimaryPfo : primaryPfoVector)
116 pfoToIdMap.insert(PfoToIdMap::value_type(pPrimaryPfo, ++pfoIndex));
119 if (pRecoTestBeam && !testBeamPfoToIdMap.count(pRecoTestBeam))
120 testBeamPfoToIdMap.insert(PfoToIdMap::value_type(pRecoTestBeam, ++testBeamPfoIndex));
125 MCParticleList associatedMCPrimaries;
127 int nCorrectTB(0), nTotalTB(0), nCorrectCR(0), nTotalCR(0), nFakeTB(0), nFakeCR(0), nSplitTB(0), nSplitCR(0), nLost(0);
128 int mcPrimaryIndex(0), nTargetMatches(0), nTargetTBMatches(0), nTargetCRMatches(0), nTargetGoodTBMatches(0);
129 IntVector mcPrimaryId, mcPrimaryPdg, nMCHitsTotal, nMCHitsU, nMCHitsV, nMCHitsW;
130 FloatVector mcPrimaryE, mcPrimaryPX, mcPrimaryPY, mcPrimaryPZ;
131 FloatVector mcPrimaryVtxX, mcPrimaryVtxY, mcPrimaryVtxZ, mcPrimaryEndX, mcPrimaryEndY, mcPrimaryEndZ;
132 IntVector nPrimaryMatchedPfos, nPrimaryMatchedTBPfos, nPrimaryMatchedCRPfos;
133 IntVector bestMatchPfoId, bestMatchPfoPdg, bestMatchPfoIsTB;
134 IntVector bestMatchPfoNHitsTotal, bestMatchPfoNHitsU, bestMatchPfoNHitsV, bestMatchPfoNHitsW;
135 IntVector bestMatchPfoNSharedHitsTotal, bestMatchPfoNSharedHitsU, bestMatchPfoNSharedHitsV, bestMatchPfoNSharedHitsW;
136 FloatVector bestMatchPfoX0;
138 std::stringstream targetSS;
140 for (
const MCParticle *
const pMCPrimary : mcPrimaryVector)
142 const bool hasMatch(mcToPfoHitSharingMap.count(pMCPrimary) && !mcToPfoHitSharingMap.at(pMCPrimary).empty());
143 const bool isTargetPrimary(validationInfo.GetTargetMCParticleToHitsMap().count(pMCPrimary));
145 if (!isTargetPrimary && !hasMatch)
148 associatedMCPrimaries.push_back(pMCPrimary);
150 const CaloHitList &mcPrimaryHitList(validationInfo.GetAllMCParticleToHitsMap().at(pMCPrimary));
156 const int nTargetPrimaries(associatedMCPrimaries.size());
158 const float targetVertexX(targetVertex.GetX()), targetVertexY(targetVertex.GetY()), targetVertexZ(targetVertex.GetZ());
161 targetSS << (!isTargetPrimary ?
"(Non target) " :
"") <<
"PrimaryId " << mcPrimaryIndex <<
", TB " << isBeamParticle <<
", CR "
162 << isCosmicRay <<
", MCPDG " << pMCPrimary->GetParticleId() <<
", Energy " << pMCPrimary->GetEnergy() <<
", Dist. "
163 << (pMCPrimary->GetEndpoint() - pMCPrimary->GetVertex()).GetMagnitude() <<
", nMCHits " << mcPrimaryHitList.size() <<
" ("
168 mcPrimaryId.push_back(mcPrimaryIndex);
169 mcPrimaryPdg.push_back(pMCPrimary->GetParticleId());
170 mcPrimaryE.push_back(pMCPrimary->GetEnergy());
171 mcPrimaryPX.push_back(pMCPrimary->GetMomentum().GetX());
172 mcPrimaryPY.push_back(pMCPrimary->GetMomentum().GetY());
173 mcPrimaryPZ.push_back(pMCPrimary->GetMomentum().GetZ());
174 mcPrimaryVtxX.push_back(pMCPrimary->GetVertex().GetX());
175 mcPrimaryVtxY.push_back(pMCPrimary->GetVertex().GetY());
176 mcPrimaryVtxZ.push_back(pMCPrimary->GetVertex().GetZ());
177 mcPrimaryEndX.push_back(pMCPrimary->GetEndpoint().GetX());
178 mcPrimaryEndY.push_back(pMCPrimary->GetEndpoint().GetY());
179 mcPrimaryEndZ.push_back(pMCPrimary->GetEndpoint().GetZ());
180 nMCHitsTotal.push_back(mcPrimaryHitList.size());
185 int matchIndex(0), nPrimaryMatches(0), nPrimaryTBMatches(0), nPrimaryCRMatches(0), nPrimaryGoodNuMatches(0);
187 float recoVertexX(std::numeric_limits<float>::max()), recoVertexY(std::numeric_limits<float>::max()),
188 recoVertexZ(std::numeric_limits<float>::max());
192 const CaloHitList &sharedHitList(pfoToSharedHits.second);
193 const CaloHitList &pfoHitList(validationInfo.GetPfoToHitsMap().at(pfoToSharedHits.first));
196 const bool isGoodMatch(this->
IsGoodMatch(mcPrimaryHitList, pfoHitList, sharedHitList));
198 const int pfoId(pfoToIdMap.at(pfoToSharedHits.first));
200 if (0 == matchIndex++)
202 bestMatchPfoId.push_back(pfoId);
203 bestMatchPfoPdg.push_back(pfoToSharedHits.first->GetParticleId());
204 bestMatchPfoIsTB.push_back(isRecoTestBeam ? 1 : 0);
205 bestMatchPfoNHitsTotal.push_back(pfoHitList.size());
209 bestMatchPfoNSharedHitsTotal.push_back(sharedHitList.size());
213 bestMatchPfoX0.push_back(pfoToSharedHits.first->GetPropertiesMap().count(
"X0") ? pfoToSharedHits.first->GetPropertiesMap().at(
"X0")
214 : std::numeric_limits<float>::max());
220 recoVertexX = pRecoVertex->GetPosition().GetX();
221 recoVertexY = pRecoVertex->GetPosition().GetY();
222 recoVertexZ = pRecoVertex->GetPosition().GetZ();
224 catch (
const StatusCodeException &)
233 if (isRecoTestBeam && isGoodMatch)
235 if (!isRecoTestBeam && isGoodMatch)
238 targetSS <<
"-" << (!isGoodMatch ?
"(Below threshold) " :
"") <<
"MatchedPfoId " << pfoId <<
", TB " << isRecoTestBeam
239 <<
", CR " << (!isRecoTestBeam) <<
", PDG " << pfoToSharedHits.first->GetParticleId() <<
", nMatchedHits "
248 if (mcToPfoHitSharingMap.at(pMCPrimary).empty())
250 targetSS <<
"-No matched Pfo" << std::endl;
251 bestMatchPfoId.push_back(-1);
252 bestMatchPfoPdg.push_back(0);
253 bestMatchPfoIsTB.push_back(0);
254 bestMatchPfoNHitsTotal.push_back(0);
255 bestMatchPfoNHitsU.push_back(0);
256 bestMatchPfoNHitsV.push_back(0);
257 bestMatchPfoNHitsW.push_back(0);
258 bestMatchPfoNSharedHitsTotal.push_back(0);
259 bestMatchPfoNSharedHitsU.push_back(0);
260 bestMatchPfoNSharedHitsV.push_back(0);
261 bestMatchPfoNSharedHitsW.push_back(0);
262 bestMatchPfoX0.push_back(std::numeric_limits<float>::max());
265 nPrimaryMatchedPfos.push_back(nPrimaryMatches);
266 nPrimaryMatchedTBPfos.push_back(nPrimaryTBMatches);
267 nPrimaryMatchedCRPfos.push_back(nPrimaryCRMatches);
268 nTargetMatches += nPrimaryMatches;
269 nTargetTBMatches += nPrimaryTBMatches;
270 nTargetCRMatches += nPrimaryCRMatches;
271 nTargetGoodTBMatches += nPrimaryGoodNuMatches;
276 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"eventNumber",
m_eventNumber - 1));
277 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcNuanceCode", mcNuanceCode));
278 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"isBeamParticle", isBeamParticle));
279 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"isCosmicRay", isCosmicRay));
280 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"nTargetPrimaries", nTargetPrimaries));
281 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"targetVertexX", targetVertexX));
282 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"targetVertexY", targetVertexY));
283 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"targetVertexZ", targetVertexZ));
284 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"recoVertexX", recoVertexX));
285 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"recoVertexY", recoVertexY));
286 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"recoVertexZ", recoVertexZ));
287 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryId", &mcPrimaryId));
288 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryPdg", &mcPrimaryPdg));
289 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryE", &mcPrimaryE));
290 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryPX", &mcPrimaryPX));
291 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryPY", &mcPrimaryPY));
292 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryPZ", &mcPrimaryPZ));
293 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryVtxX", &mcPrimaryVtxX));
294 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryVtxY", &mcPrimaryVtxY));
295 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryVtxZ", &mcPrimaryVtxZ));
296 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryEndX", &mcPrimaryEndX));
297 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryEndY", &mcPrimaryEndY));
298 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryEndZ", &mcPrimaryEndZ));
299 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryNHitsTotal", &nMCHitsTotal));
300 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryNHitsU", &nMCHitsU));
301 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryNHitsV", &nMCHitsV));
302 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"mcPrimaryNHitsW", &nMCHitsW));
303 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"nPrimaryMatchedPfos", &nPrimaryMatchedPfos));
304 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"nPrimaryMatchedTBPfos", &nPrimaryMatchedTBPfos));
305 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"nPrimaryMatchedCRPfos", &nPrimaryMatchedCRPfos));
306 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"bestMatchPfoId", &bestMatchPfoId));
307 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"bestMatchPfoPdg", &bestMatchPfoPdg));
308 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"bestMatchPfoNHitsTotal", &bestMatchPfoNHitsTotal));
309 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"bestMatchPfoNHitsU", &bestMatchPfoNHitsU));
310 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"bestMatchPfoNHitsV", &bestMatchPfoNHitsV));
311 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"bestMatchPfoNHitsW", &bestMatchPfoNHitsW));
312 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"bestMatchPfoNSharedHitsTotal", &bestMatchPfoNSharedHitsTotal));
313 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"bestMatchPfoNSharedHitsU", &bestMatchPfoNSharedHitsU));
314 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"bestMatchPfoNSharedHitsV", &bestMatchPfoNSharedHitsV));
315 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"bestMatchPfoNSharedHitsW", &bestMatchPfoNSharedHitsW));
316 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"bestMatchPfoX0", &bestMatchPfoX0));
317 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"nTargetMatches", nTargetMatches));
318 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"nTargetTBMatches", nTargetTBMatches));
319 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"nTargetCRMatches", nTargetCRMatches));
320 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"bestMatchPfoIsTB", &bestMatchPfoIsTB));
323 if (isBeamParticle || isCosmicRay)
327 const int interactionTypeInt(static_cast<int>(interactionType));
330 const int isCorrectTB(isBeamParticle && (nTargetTBMatches == 1) && (nTargetCRMatches == 0));
331 const int isCorrectCR(isCosmicRay && (nTargetTBMatches == 0) && (nTargetCRMatches == 1));
332 const int isFakeTB(isCosmicRay && (nTargetTBMatches > 0));
333 const int isFakeCR(!isCosmicRay && (nTargetCRMatches > 0));
334 const int isSplitTB(!isCosmicRay && (nTargetTBMatches > 1));
335 const int isSplitCR(isCosmicRay && (nTargetCRMatches > 1));
336 const int isLost(nTargetMatches == 0);
338 std::stringstream outcomeSS;
340 <<
", CR " << isCosmicRay <<
")" << std::endl;
362 outcomeSS <<
"IsCorrectTB ";
364 outcomeSS <<
"IsCorrectCR ";
366 outcomeSS <<
"IsFakeTB ";
368 outcomeSS <<
"IsFakeCR ";
370 outcomeSS <<
"isSplitTB ";
372 outcomeSS <<
"IsSplitCR ";
374 outcomeSS <<
"IsLost ";
375 if (nTargetTBMatches > 0)
376 outcomeSS <<
"(NTBMatches: " << nTargetTBMatches <<
") ";
377 if (nTargetCRMatches > 0)
378 outcomeSS <<
"(NCRMatches: " << nTargetCRMatches <<
") ";
380 std::cout << outcomeSS.str() << std::endl << targetSS.str() << std::endl;
384 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"interactionType", interactionTypeInt));
385 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"isCorrectTB", isCorrectTB));
386 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"isCorrectCR", isCorrectCR));
387 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"isFakeTB", isFakeTB));
388 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"isFakeCR", isFakeCR));
389 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"isSplitTB", isSplitTB));
390 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"isSplitCR", isSplitCR));
391 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(),
m_treeName.c_str(),
"isLost", isLost));
392 PANDORA_MONITORING_API(FillTree(this->GetPandora(),
m_treeName.c_str()));
395 targetSS.str(std::string());
397 associatedMCPrimaries.clear();
399 nTargetTBMatches = 0;
400 nTargetCRMatches = 0;
401 nTargetGoodTBMatches = 0;
403 mcPrimaryPdg.clear();
404 nMCHitsTotal.clear();
412 mcPrimaryVtxX.clear();
413 mcPrimaryVtxY.clear();
414 mcPrimaryVtxZ.clear();
415 mcPrimaryEndX.clear();
416 mcPrimaryEndY.clear();
417 mcPrimaryEndZ.clear();
418 nPrimaryMatchedPfos.clear();
419 nPrimaryMatchedTBPfos.clear();
420 nPrimaryMatchedCRPfos.clear();
421 bestMatchPfoId.clear();
422 bestMatchPfoPdg.clear();
423 bestMatchPfoIsTB.clear();
424 bestMatchPfoNHitsTotal.clear();
425 bestMatchPfoNHitsU.clear();
426 bestMatchPfoNHitsV.clear();
427 bestMatchPfoNHitsW.clear();
428 bestMatchPfoNSharedHitsTotal.clear();
429 bestMatchPfoNSharedHitsU.clear();
430 bestMatchPfoNSharedHitsV.clear();
431 bestMatchPfoNSharedHitsW.clear();
432 bestMatchPfoX0.clear();
436 if (useInterpretedMatching)
438 std::stringstream summarySS;
439 summarySS <<
"---SUMMARY--------------------------------------------------------------------------------------" << std::endl;
441 summarySS <<
"#CorrectTB: " << nCorrectTB <<
"/" << nTotalTB
442 <<
", Fraction: " << (nTotalTB > 0 ?
static_cast<float>(nCorrectTB) / static_cast<float>(nTotalTB) : 0.f) <<
std::endl;
444 summarySS <<
"#CorrectCR: " << nCorrectCR <<
"/" << nTotalCR
445 <<
", Fraction: " << (nTotalCR > 0 ?
static_cast<float>(nCorrectCR) / static_cast<float>(nTotalCR) : 0.f) <<
std::endl;
447 summarySS <<
"#FakeTB: " << nFakeTB <<
" ";
449 summarySS <<
"#FakeCR: " << nFakeCR <<
" ";
451 summarySS <<
"#SplitTB: " << nSplitTB <<
" ";
453 summarySS <<
"#SplitCR: " << nSplitCR <<
" ";
455 summarySS <<
"#Lost: " << nLost <<
" ";
456 if (nFakeTB || nFakeCR || nSplitTB || nSplitCR || nLost)
457 summarySS << std::endl;
463 std::cout <<
"------------------------------------------------------------------------------------------------" << std::endl
std::unordered_map< const pandora::ParticleFlowObject *, unsigned int > PfoToIdMap
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
int m_eventNumber
The event number.
int m_fileIdentifier
The input file identifier.
static const pandora::Vertex * GetVertex(const pandora::ParticleFlowObject *const pPfo)
Get the pfo vertex.
static const pandora::Vertex * GetTestBeamInteractionVertex(const pandora::ParticleFlowObject *const pPfo)
Get the pfo test beam interaction vertex.
std::map< const pandora::MCParticle *, PfoToSharedHitsVector > MCParticleToPfoHitSharingMap
std::vector< int > IntVector
static unsigned int GetNuanceCode(const pandora::MCParticle *const pMCParticle)
Get the nuance code of an MCParticle.
static InteractionType GetInteractionType(const pandora::MCParticleList &mcPrimaryList)
Get the interaction type of an event.
static void GetOrderedMCParticleVector(const LArMCParticleHelper::MCContributionMapVector &selectedMCParticleToGoodHitsMaps, pandora::MCParticleVector &orderedMCParticleVector)
Order input MCParticles by their number of hits.
static bool IsCosmicRay(const pandora::MCParticle *const pMCParticle)
Return true if passed a primary cosmic ray MCParticle.
static bool IsTestBeam(const pandora::ParticleFlowObject *const pPfo)
Whether a pfo is a test beam particle.
std::unordered_map< const pandora::MCParticle *, int > MCParticleIntMap
static const pandora::ParticleFlowObject * GetParentPfo(const pandora::ParticleFlowObject *const pPfo)
Get the primary parent pfo.
static std::string ToString(const InteractionType interactionType)
Get a string representation of an interaction type.
static bool IsBeamParticle(const pandora::MCParticle *const pMCParticle)
Returns true if passed a primary beam MCParticle.
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
static const pandora::MCParticle * GetParentMCParticle(const pandora::MCParticle *const pMCParticle)
Get the parent mc particle.
static void GetOrderedPfoVector(const LArMCParticleHelper::PfoContributionMap &pfoToReconstructable2DHitsMap, pandora::PfoVector &orderedPfoVector)
Order input Pfos by their number of hits.
InteractionType
InteractionType enum.
std::pair< const pandora::ParticleFlowObject *, pandora::CaloHitList > PfoCaloHitListPair
std::string m_treeName
Name of output tree.
bool IsGoodMatch(const pandora::CaloHitList &trueHits, const pandora::CaloHitList &recoHits, const pandora::CaloHitList &sharedHits) const
Whether a provided mc primary and pfo are deemed to be a good match.
static unsigned int CountHitsByType(const pandora::HitType hitType, const pandora::CaloHitList &caloHitList)
Count the number of calo hits, in a provided list, of a specified type.
static bool IsTestBeamFinalState(const pandora::ParticleFlowObject *const pPfo)
Whether a pfo is a final-state particle from a test beam particle interaction.
BEGIN_PROLOG could also be cout