LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
IndirectHitParticleAssns_tool.cc
Go to the documentation of this file.
2 
4 
6 
12 #include "fhiclcpp/ParameterSet.h"
14 
15 namespace t0 {
17  //
18  // Class: IndirectHitParticleAssns
19  // Module Type: art tool
20  // File: IndirectHitParticleAssns.h
21  //
22  // This provides MC truth information by using output
23  // reco Hit <--> MCParticle associations
24  //
25  // Configuration parameters:
26  //
27  // TruncMeanFraction - the fraction of waveform bins to discard when
28  //
29  // Created by Tracy Usher (usher@slac.stanford.edu) on November 21, 2017
30  //
32 
34  public:
40  explicit IndirectHitParticleAssns(fhicl::ParameterSet const& pset);
41 
42  // provide for initialization
43  void reconfigure(fhicl::ParameterSet const& pset) override;
44 
49 
50  private:
51  std::vector<art::InputTag> fHitModuleLabelVec;
54  };
55 
56  //----------------------------------------------------------------------------
64  {
65  reconfigure(pset);
66 
67  // Report.
68  mf::LogInfo("IndirectHitParticleAssns") << "Configured\n";
69  }
70 
71  //----------------------------------------------------------------------------
79  {
80  fHitPartAssnsModuleLabel = pset.get<art::InputTag>("HitPartAssnsLabel");
81  fMCParticleModuleLabel = pset.get<art::InputTag>("MCParticleModuleLabel");
82  fHitModuleLabelVec = pset.get<std::vector<art::InputTag>>("HitModuleLabelVec");
83  }
84 
85  //----------------------------------------------------------------------------
93  art::Event& evt,
94  HitParticleAssociations* hitPartAssns)
95  {
96  // This function handles the "indirect" creation of hit<-->MCParticle associations by trying to
97  // use the previously created Hit<-->MCParticle associations
98  // Its pretty much a brute force approach here... but time is short!
99  //
100  // First step is to recover the preexisting associations
101 
102  // Get a handle for the associations...
103  auto partHitAssnsHandle = evt.getValidHandle<HitParticleAssociations>(fHitPartAssnsModuleLabel);
104  auto mcParticleHandle =
105  evt.getValidHandle<std::vector<simb::MCParticle>>(fMCParticleModuleLabel);
106 
107  if (!partHitAssnsHandle.isValid() || !mcParticleHandle.isValid()) {
108  throw cet::exception("IndirectHitParticleAssns")
109  << "===>> NO MCParticle <--> Hit associations found for run/subrun/event: " << evt.run()
110  << "/" << evt.subRun() << "/" << evt.id().event();
111  }
112 
113  // Loop over input hit collections
114  for (const auto& inputTag : fHitModuleLabelVec) {
115  // Look up the hits we want to process as well, since if they are not there then no point in proceeding
117  evt.getByLabel(inputTag, hitListHandle);
118 
119  if (!hitListHandle.isValid()) {
120  mf::LogInfo("IndirectHitParticleAssns")
121  << "===>> NO Hit collection found to process for run/subrun/event: " << evt.run() << "/"
122  << evt.subRun() << "/" << evt.id().event() << "\n";
123  continue;
124  }
125 
126  // Go through the associations and build out our (hopefully sparse) data structure
127  using ParticleDataPair = std::pair<size_t, const anab::BackTrackerHitMatchingData*>;
128  using MCParticleDataSet = std::set<ParticleDataPair>;
129  using TickToPartDataMap = std::unordered_map<raw::TDCtick_t, MCParticleDataSet>;
130  using ChannelToTickPartDataMap = std::unordered_map<raw::ChannelID_t, TickToPartDataMap>;
131 
132  ChannelToTickPartDataMap chanToTickPartDataMap;
133 
134  // Build out the maps between hits/particles
135  for (HitParticleAssociations::const_iterator partHitItr = partHitAssnsHandle->begin();
136  partHitItr != partHitAssnsHandle->end();
137  ++partHitItr) {
138  const art::Ptr<simb::MCParticle>& mcParticle = partHitItr->first;
139  const art::Ptr<recob::Hit>& recoHit = partHitItr->second;
140  const anab::BackTrackerHitMatchingData* data = &partHitAssnsHandle->data(partHitItr);
141 
142  TickToPartDataMap& tickToPartDataMap = chanToTickPartDataMap[recoHit->Channel()];
143 
144  for (raw::TDCtick_t tick = recoHit->PeakTimeMinusRMS(); tick <= recoHit->PeakTimePlusRMS();
145  tick++) {
146  tickToPartDataMap[tick].insert(ParticleDataPair(mcParticle.key(), data));
147  }
148  }
149 
150  // Armed with the map, process the hit list
151  for (size_t hitIdx = 0; hitIdx < hitListHandle->size(); hitIdx++) {
152  art::Ptr<recob::Hit> hit(hitListHandle, hitIdx);
153 
154  TickToPartDataMap& tickToPartDataMap = chanToTickPartDataMap[hit->Channel()];
155 
156  if (tickToPartDataMap.empty()) {
157  mf::LogInfo("IndirectHitParticleAssns")
158  << "No channel information found for hit " << hit << "\n";
159  continue;
160  }
161 
162  // Keep track of results
163  MCParticleDataSet particleDataSet;
164 
165  // Go through the ticks in this hit and recover associations
166  for (raw::TDCtick_t tick = hit->PeakTimeMinusRMS(); tick <= hit->PeakTimePlusRMS();
167  tick++) {
168  TickToPartDataMap::iterator hitInfoItr = tickToPartDataMap.find(tick);
169 
170  if (hitInfoItr != tickToPartDataMap.end()) {
171  for (const auto& partData : hitInfoItr->second)
172  particleDataSet.insert(partData);
173  }
174  }
175 
176  // Now create new associations for the hit in question
177  for (const auto& partData : particleDataSet)
178  hitPartAssns->addSingle(
179  art::Ptr<simb::MCParticle>(mcParticleHandle, partData.first), hit, *partData.second);
180  }
181  }
182 
183  return;
184  }
185 
186  //----------------------------------------------------------------------------
187 
189 }
code to link reconstructed objects back to the MC truth information
intermediate_table::iterator iterator
SubRunNumber_t subRun() const
Definition: Event.cc:35
#define DEFINE_ART_CLASS_TOOL(tool)
Definition: ToolMacros.h:42
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
void CreateHitParticleAssociations(art::Event &, HitParticleAssociations *) override
This rebuilds the internal maps.
Declaration of signal hit object.
Particle class.
int TDCtick_t
Type representing a TDC tick.
Definition: RawTypes.h:25
bool isValid() const noexcept
Definition: Handle.h:203
void reconfigure(fhicl::ParameterSet const &pset) override
std::vector< art::InputTag > fHitModuleLabelVec
key_type key() const noexcept
Definition: Ptr.h:166
T get(std::string const &key) const
Definition: ParameterSet.h:314
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:73
float PeakTimeMinusRMS(float sigmas=+1.) const
Returns a time sigmas RMS away from the peak time.
Definition: Hit.h:290
Detector simulation of raw signals on wires.
IndirectHitParticleAssns(fhicl::ParameterSet const &pset)
Constructor.
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
void addSingle(Ptr< left_t > const &left, Ptr< right_t > const &right, data_t const &data)
Definition: Assns.h:549
EventNumber_t event() const
Definition: EventID.h:116
float PeakTimePlusRMS(float sigmas=+1.) const
Returns a time sigmas RMS away from the peak time.
Definition: Hit.h:285
TCEvent evt
Definition: DataStructs.cxx:8
RunNumber_t run() const
Definition: Event.cc:29
raw::ChannelID_t Channel() const
ID of the readout channel the hit was extracted from.
Definition: Hit.h:268
Definition: fwd.h:26
typename art::const_AssnsIter< L, R, D, Direction::Forward > const_iterator
Definition: Assns.h:239
EventID id() const
Definition: Event.cc:23
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33