Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First pass at extracting digis from tracks #1343

Merged
merged 3 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions Blinding/src/SConscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env python

import os, re

Import('env')
Import('mu2e_helper')

helper = mu2e_helper(env)
rootlibs = env['ROOTLIBS']

mainlib = helper.make_mainlib([
'gmp',
'gmpxx',
])

helper.make_plugins([
mainlib,
'art_Framework_Core',
'art_Framework_Services_Registry',
'art_Framework_Principal',
'art_Persistency_Provenance',
'art_Utilities',
'canvas',
'cetlib',
'cetlib_except',
'fhiclcpp',
'fhiclcpp_types',
'gmp',
'gmpxx',
'mu2e_DataProducts',
'mu2e_DbTables',
'mu2e_ProditionsService',
'mu2e_RecoDataProducts',
'mu2e_SeedService',
'mu2e_TrackerConditions',
'mu2e_TrackerMC',
])
122 changes: 122 additions & 0 deletions Blinding/src/TrackDigiExtractor_module.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Ed Callaghan
// Extract digis which participate in a prefit track
// September 2024

// stl
#include <string>

// art
#include "art/Framework/Core/EDProducer.h"
#include "art/Framework/Principal/Event.h"

// cetlib_except
#include "cetlib_except/exception.h"

// fhiclcpp
#include "fhiclcpp/types/Atom.h"
#include "fhiclcpp/types/Comment.h"
#include "fhiclcpp/types/Name.h"

// mu2e
#include "Offline/RecoDataProducts/inc/KalSeed.hh"
#include "Offline/RecoDataProducts/inc/StrawHit.hh"
#include "Offline/RecoDataProducts/inc/StrawDigi.hh"
#include "Offline/RecoDataProducts/inc/TrkStrawHitSeed.hh"

namespace mu2e{
class TrackDigiExtractor: public art::EDProducer{
public:
struct Config{
// track
fhicl::Atom<art::InputTag> kalseed_tag{
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it conceivable this module will need to coherently process multiple KalSeed collections (ie multiple particle hypotheses)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is conceivable, but IMO unlikely for the conversion-blinding use case where we really only want electron-like tracks. Maybe we'll determine that selecting another stream is useful for some book-keeping purpose, but I doubt that we'd want to collate that with the electron-likes at this stage.

fhicl::Name("KalSeedCollection"),
fhicl::Comment("art::InputTag of KalSeeds to extract digis from")
};

// tracker
fhicl::Atom<art::InputTag> strawhit_tag{
fhicl::Name("StrawHitCollection"),
fhicl::Comment("art::InputTag of StrawHits associated with KalSeed")
};
fhicl::Atom<art::InputTag> strawdigi_tag{
fhicl::Name("StrawDigiCollection"),
fhicl::Comment("art::InputTag of StrawDigis associated with StrawHits")
};

// calorimeter...
};

using Parameters = art::EDProducer::Table<Config>;
TrackDigiExtractor(const Parameters&);

protected:
art::InputTag _kalseed_tag;
art::InputTag _strawhit_tag;
art::InputTag _strawdigi_tag;

private:
void produce(art::Event&);
};

TrackDigiExtractor::TrackDigiExtractor(const Parameters& config):
art::EDProducer(config),
_kalseed_tag(config().kalseed_tag()),
_strawhit_tag(config().strawhit_tag()),
_strawdigi_tag(config().strawdigi_tag()){
this->consumes<KalSeedCollection>(_kalseed_tag);
this->consumes<StrawHitCollection>(_strawhit_tag);
this->consumes<StrawDigiCollection>(_strawdigi_tag);
this->consumes<StrawDigiADCWaveformCollection>(_strawdigi_tag);
this->produces<StrawDigiCollection>();
this->produces<StrawDigiADCWaveformCollection>();
}

void TrackDigiExtractor::produce(art::Event& event){
// data-product lookups
auto kalseeds = event.getValidHandle<KalSeedCollection>(_kalseed_tag);
auto strawhits = event.getValidHandle<StrawHitCollection>(_strawhit_tag);
auto strawdigis = event.getValidHandle<StrawDigiCollection>(_strawdigi_tag);
auto strawadcss = event.getValidHandle<StrawDigiADCWaveformCollection>(_strawdigi_tag);

// sanity checks
if (strawhits->size() != strawdigis->size()){
Copy link
Collaborator

Choose a reason for hiding this comment

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

This test relies on this module's config being consistent with what was used when fitting the tracks.

A way to ensure consistency is to use the KKTrack instead of KalSeed; KKTrack can have Ptrs back to underlying collections, but it cannot be persisted, due to payload that includes std::Ptrs. We can discuss if that makes sense in this context.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmmm, ok. The current implementation does depend on this check passing, as e.g. StrawHits and StrawDigis do not contain any ptrs to each other. To be sure that both for a given hit are included, we have to assume that the collections in which they are contained are aligned (and the best check we have for that is same-length).

Copy link
Collaborator

Choose a reason for hiding this comment

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

There is a long-term issue that we need to improve the robustness of the digi->hit->trkhit indexing using ProductPtr, which didn't exist when the original codes were written. That's beyond the scope of this PR. We can deal with this code when we address that issue in general.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good to me.

std::string msg = "mismatched StrawHit and StrawDigi collection lengths";
throw cet::exception("TrackDigiExtractor") << msg << std::endl;
}
if (strawdigis->size() != strawadcss->size()){
std::string msg = "mismatched StrawDigi and StrawDigiADCWaveform collection lengths";
throw cet::exception("TrackDigiExtractor") << msg << std::endl;
}

// deep-copy digis underlying tracks
auto ext_strawdigis = std::make_unique<StrawDigiCollection>();
auto ext_strawadcss = std::make_unique<StrawDigiADCWaveformCollection>();
for (const auto& kalseed: *kalseeds){
// tracker
auto seeds = kalseed.hits();
for (const auto& seed: seeds){
Copy link
Collaborator

Choose a reason for hiding this comment

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

Its not clear to me we want to keep the inactive hits in this use case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The only place I can identify this being set is in the TrkStrawHitSeed constructor, where it propagates from a WireHitState --- it looks like this is still a fit-level construct (e.g., it contains the decision on left/right ambiguity), so is contextual to the fit. If that's the case, then I think we'd want to keep the inactive hits, as they could become active when fit in the presence of pileup. Is that a reasonable take?

Or, if I'm wrong about the above, then we have to ask whether only propagating active hits risks a break in blindness. Since these are overlaid onto pileup which could contribute hits to the fit but end up inactive, the answer may be no, but it's worth mentioning.

Copy link
Collaborator

Choose a reason for hiding this comment

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

In OffSpill cosmic track events, the inactive hits will mostly be poorly measured hits created by the primary particle, so you want to keep them. However in a mixed event, many/most of the inactive hits will be from pileup, so you would not want to keep them if you planned to re-mix the extracted digis.
I think the current code covers 90% of the foreseeable use cases, lets go with this for now. If in future we want to use this code to extract digis from events with pileup we can extend it to include a hit selection algorithm.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, that all makes sense.

auto idx = seed.index();
auto hit = (*strawhits)[idx];
auto digi = (*strawdigis)[idx];
auto adcs = (*strawadcss)[idx];

// sanity check
if (hit.strawId() != digi.strawId()){
std::string msg = "mismatched StrawHit and StrawDigi StrawIDs";
throw cet::exception("TrackDigiExtractor") << msg << std::endl;
}

ext_strawdigis->push_back(digi);
ext_strawadcss->push_back(adcs);
}

// calorimeter...
}

// place into event
event.put(std::move(ext_strawdigis));
event.put(std::move(ext_strawadcss));
}
} // namespace mu2e

DEFINE_ART_MODULE(mu2e::TrackDigiExtractor)