Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include <UTIL/LCRelationNavigator.h>

class IsolatedLeptonFinderProcessor : public marlin::Processor {

public:
virtual Processor* newProcessor() { return new IsolatedLeptonFinderProcessor; }

Expand All @@ -37,6 +36,10 @@ class IsolatedLeptonFinderProcessor : public marlin::Processor {
virtual void processEvent(LCEvent* evt);
virtual void end();

private:
/// Return the original PFO if this particle is a copy, otherwise return itself
ReconstructedParticle* findOriginal(ReconstructedParticle* pfo) const;

protected:
/** Returns true if pfo is a lepton */
bool IsGoodLepton(ReconstructedParticle* pfo);
Expand Down Expand Up @@ -167,6 +170,23 @@ class IsolatedLeptonFinderProcessor : public marlin::Processor {

/** If set to true, uses Pandora particle IDs */
bool _usePandoraIDs = false;

/**
* Map from internally copied PFOs to their original input PFOs.
*
* The IsolatedLeptonFinder creates internal copies of ReconstructedParticles
* (e.g. for dressing leptons or producing modified output collections).
* However, isolation quantities such as the cone energy are defined with
* respect to the original input PFO collection.
*
* Since the copied PFOs are distinct objects, pointer comparisons would
* otherwise fail (e.g. when excluding the lepton itself from the cone),
* leading to incorrect self-counting in the isolation energy.
*
* This map is therefore used to recover the association to the original
* PFO when computing isolation-related quantities.
*/
std::map<ReconstructedParticle*, ReconstructedParticle*> _copy2orig;
};

#endif
54 changes: 34 additions & 20 deletions Analysis/IsolatedLeptonFinder/src/IsolatedLeptonFinderProcessor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ using namespace marlin;

IsolatedLeptonFinderProcessor aIsolatedLeptonFinderProcessor;

IsolatedLeptonFinderProcessor::IsolatedLeptonFinderProcessor() : Processor("IsolatedLeptonFinderProcessor") {

IsolatedLeptonFinderProcessor::IsolatedLeptonFinderProcessor()
: Processor("IsolatedLeptonFinderProcessor"), _copy2orig() {
// Processor description
_description = "Isolated Lepton Finder Processor";

Expand Down Expand Up @@ -180,7 +180,16 @@ void IsolatedLeptonFinderProcessor::init() {
printParameters();
}

ReconstructedParticle* IsolatedLeptonFinderProcessor::findOriginal(ReconstructedParticle* pfo) const {
const auto it = _copy2orig.find(pfo);
if (it != _copy2orig.end()) {
return it->second;
}
return pfo;
}

void IsolatedLeptonFinderProcessor::processEvent(LCEvent* evt) {
_copy2orig.clear(); // Clear copy-origin map

streamlog_out(DEBUG) << std::endl;
streamlog_out(DEBUG) << "processing event: " << evt->getEventNumber() << " in run: " << evt->getRunNumber()
Expand Down Expand Up @@ -238,6 +247,7 @@ void IsolatedLeptonFinderProcessor::processEvent(LCEvent* evt) {
ReconstructedParticle* pfo_tmp =
static_cast<ReconstructedParticle*>(_pfoCol->getElementAt(goodLeptonIndices.at(i)));
ReconstructedParticleImpl* pfo = CopyReconstructedParticle(pfo_tmp);
_copy2orig[pfo] = pfo_tmp; // Map the address copy-original

if (_useDressedLeptons) {
// don't reprocess merged leptons
Expand Down Expand Up @@ -334,9 +344,10 @@ void IsolatedLeptonFinderProcessor::dressLepton(ReconstructedParticleImpl* pfo,
}
}
void IsolatedLeptonFinderProcessor::end() {}

ReconstructedParticleImpl* IsolatedLeptonFinderProcessor::CopyReconstructedParticle(ReconstructedParticle* pfo_orig) {
// copy this in an ugly fashion to be modifiable - a versatile copy constructor would be much better!
ReconstructedParticleImpl* pfo = new ReconstructedParticleImpl();

pfo->setMomentum(pfo_orig->getMomentum());
pfo->setEnergy(pfo_orig->getEnergy());
pfo->setType(pfo_orig->getType());
Expand All @@ -346,14 +357,18 @@ ReconstructedParticleImpl* IsolatedLeptonFinderProcessor::CopyReconstructedParti
pfo->setParticleIDUsed(pfo_orig->getParticleIDUsed());
pfo->setGoodnessOfPID(pfo_orig->getGoodnessOfPID());
pfo->setStartVertex(pfo_orig->getStartVertex());
for (unsigned int i = 0; i < pfo->getTracks().size(); i++) {

// FIXED

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// FIXED

Looks like another leftover from development.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, those comments was written earlier and forgot to arrange them

for (unsigned int i = 0; i < pfo_orig->getTracks().size(); i++) {
pfo->addTrack(pfo_orig->getTracks()[i]);
}
for (unsigned int i = 0; i < pfo->getClusters().size(); i++) {
for (unsigned int i = 0; i < pfo_orig->getClusters().size(); i++) {
pfo->addCluster(pfo_orig->getClusters()[i]);
}

return pfo;
}

bool IsolatedLeptonFinderProcessor::IsCharged(ReconstructedParticle* pfo) {
if (pfo->getCharge() == 0)
return false;
Expand All @@ -366,7 +381,6 @@ bool IsolatedLeptonFinderProcessor::IsPhoton(ReconstructedParticle* pfo) {
return false;
}
bool IsolatedLeptonFinderProcessor::IsElectron(ReconstructedParticle* pfo) {

if (_usePandoraIDs)
return (abs(pfo->getType()) == 11);

Expand All @@ -386,7 +400,6 @@ bool IsolatedLeptonFinderProcessor::IsElectron(ReconstructedParticle* pfo) {
return false;
}
bool IsolatedLeptonFinderProcessor::IsMuon(ReconstructedParticle* pfo) {

if (_usePandoraIDs)
return (abs(pfo->getType()) == 13);

Expand All @@ -406,14 +419,12 @@ bool IsolatedLeptonFinderProcessor::IsMuon(ReconstructedParticle* pfo) {
return false;
}
bool IsolatedLeptonFinderProcessor::IsLepton(ReconstructedParticle* pfo) {

if (IsElectron(pfo) || IsMuon(pfo))
return true;
return false;
}

bool IsolatedLeptonFinderProcessor::IsGoodLepton(ReconstructedParticle* pfo) {

if (!IsCharged(pfo))
return false;

Expand All @@ -430,7 +441,6 @@ bool IsolatedLeptonFinderProcessor::IsGoodLepton(ReconstructedParticle* pfo) {
}

bool IsolatedLeptonFinderProcessor::IsIsolatedLepton(ReconstructedParticle* pfo) {

if (_useRectangularIsolation && !IsIsolatedRectangular(pfo))
return false;

Expand Down Expand Up @@ -469,27 +479,26 @@ bool IsolatedLeptonFinderProcessor::IsIsolatedPolynomial(ReconstructedParticle*
}

bool IsolatedLeptonFinderProcessor::IsIsolatedJet(ReconstructedParticle* pfo) {
// jet-based isolated lepton (LAL algorithm)
Comment thread
tmadlener marked this conversation as resolved.
ReconstructedParticle* orig = findOriginal(pfo);

if (_rpJetMap.find(pfo) == _rpJetMap.end()) {
if (_rpJetMap.find(orig) == _rpJetMap.end()) {
// this is often the case when jet finding fails e.g. due to too few particles in event
// Use original address

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move this comment further up. Alternatively, remove it entirely as it is pretty obvious from the code what we are doing, but the why we are doing it is missing. In this case the why is probably simply that the _rpJetMap stores the original PFOs, so also that is not extremely interesting, resp. can also be derived from the code in a rather straight forward manner.

return false;
}

ReconstructedParticle* jet = _rpJetMap[pfo];
TVector3 vec1(pfo->getMomentum());
ReconstructedParticle* jet = _rpJetMap[orig];
TVector3 vec1(orig->getMomentum());
TVector3 jetmom(jet->getMomentum());
TLorentzVector jetmom4(jet->getMomentum(), jet->getEnergy());

float jetxt = vec1.Pt(jetmom) / jetmom4.M();
float jetz = pfo->getEnergy() / jet->getEnergy();
float jetz = orig->getEnergy() / jet->getEnergy();

if (jetxt >= _jetIsoVetoMinXt && jetxt < _jetIsoVetoMaxXt && jetz >= _jetIsoVetoMinZ && jetz < _jetIsoVetoMaxZ) {
// printf("xt=%f z=%f (not pass)\n",jetxt,jetz);
return false;
}

// printf("xt=%f z=%f (PASS)\n",jetxt,jetz);
return true;
}

Expand Down Expand Up @@ -553,19 +562,24 @@ bool IsolatedLeptonFinderProcessor::PassesImpactParameterSignificanceCuts(Recons
}

float IsolatedLeptonFinderProcessor::getConeEnergy(ReconstructedParticle* pfo) {
ReconstructedParticle* orig = findOriginal(pfo); // Get the original address

float coneE = 0;
TVector3 P(orig->getMomentum());

TVector3 P(pfo->getMomentum());
int npfo = _workingList.size();
for (int i = 0; i < npfo; i++) {
ReconstructedParticle* pfo_i = static_cast<ReconstructedParticle*>(_workingList.at(i));
ReconstructedParticle* pfo_i = _workingList[i];

// don't add itself to the cone energy
if (pfo == pfo_i)
if (pfo_i == orig)
continue;

TVector3 P_i(pfo_i->getMomentum());
if (P.Mag() == 0 || P_i.Mag() == 0)
continue;
float cosTheta = P.Dot(P_i) / (P.Mag() * P_i.Mag());

if (cosTheta >= _cosConeAngle)
coneE += pfo_i->getEnergy();
}
Expand Down