CosmicPFParticleTagger_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: CosmicPFParticleTagger
3 // Module Type: producer
4 // File: CosmicPFParticleTagger_module.cc
5 // This module checks timing and TPC volume boundaries as a
6 // way to tag potential cosmic rays
7 // This particular module uses PFParticles as input and handles
8 // special cases associated with them.
9 // This module started life as CosmicTrackTagger_module, written
10 // by Sarah Lockwitz, and small alterations made to handle the
11 // PFParticle input
12 //
13 // Generated at Wed Sep 17 19:17:00 2014 by Tracy Usher by cloning CosmicTrackTagger
14 // from art v1_02_02.
15 // artmod -e beginJob -e reconfigure -e endJob producer trkf::CosmicPFParticleTagger
16 ////////////////////////////////////////////////////////////////////////
17 
21 
22 #include <iterator>
23 
32 
33 namespace cosmic {
34  class CosmicPFParticleTagger;
35 }
36 
38 public:
40 
41  void produce(art::Event& e) override;
42 
43 private:
49  int fMaxOutOfTime; ///< Max hits that can be out of time before rejecting
52 };
53 
55 {
56 
57  //////// fSptalg = new cosmic::SpacePointAlg(p.get<fhicl::ParameterSet>("SpacePointAlg"));
58  auto const* geo = lar::providerFrom<geo::Geometry>();
59  auto const clock_data = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
60  auto const detp =
62 
63  fDetHalfHeight = geo->DetHalfHeight();
64  fDetWidth = 2. * geo->DetHalfWidth();
65  fDetLength = geo->DetLength();
66 
67  float fSamplingRate = sampling_rate(clock_data);
68 
69  fPFParticleModuleLabel = p.get<std::string>("PFParticleModuleLabel");
70  fTrackModuleLabel = p.get<std::string>("TrackModuleLabel", "track");
71  fEndTickPadding = p.get<int>("EndTickPadding", 50); // Fudge the TPC edge in ticks...
72  fMaxOutOfTime = p.get<int>("MaxOutOfTime", 4);
73 
74  fTPCXBoundary = p.get<float>("TPCXBoundary", 5);
75  fTPCYBoundary = p.get<float>("TPCYBoundary", 5);
76  fTPCZBoundary = p.get<float>("TPCZBoundary", 5);
77 
78  const double driftVelocity = detp.DriftVelocity(detp.Efield(), detp.Temperature()); // cm/us
79 
81  2 * geo->DetHalfWidth() / (driftVelocity * fSamplingRate / 1000); // ~3200 for uB
82  fMinTickDrift = clock_data.Time2Tick(clock_data.TriggerTime());
84 
85  produces<std::vector<anab::CosmicTag>>();
86  produces<art::Assns<anab::CosmicTag, recob::Track>>();
87  produces<art::Assns<recob::PFParticle, anab::CosmicTag>>();
88 }
89 
90 void
92 {
93  // Instatiate the output
94  std::unique_ptr<std::vector<anab::CosmicTag>> cosmicTagTrackVector(
95  new std::vector<anab::CosmicTag>);
96  std::unique_ptr<art::Assns<anab::CosmicTag, recob::Track>> assnOutCosmicTagTrack(
98  std::unique_ptr<art::Assns<recob::PFParticle, anab::CosmicTag>> assnOutCosmicTagPFParticle(
100 
101  // Recover handle for PFParticles
103  evt.getByLabel(fPFParticleModuleLabel, pfParticleHandle);
104 
105  if (!pfParticleHandle.isValid()) {
106  evt.put(std::move(cosmicTagTrackVector));
107  evt.put(std::move(assnOutCosmicTagTrack));
108  return;
109  }
110 
111  // Recover the handle for the tracks
113  evt.getByLabel(fTrackModuleLabel, trackHandle);
114 
115  if (!trackHandle.isValid()) {
116  evt.put(std::move(cosmicTagTrackVector));
117  evt.put(std::move(assnOutCosmicTagTrack));
118  return;
119  }
120 
121  // Recover handle for track <--> PFParticle associations
123  evt.getByLabel(fTrackModuleLabel, pfPartToTrackHandle);
124 
125  // Recover the list of associated tracks
126  art::FindManyP<recob::Track> pfPartToTrackAssns(pfParticleHandle, evt, fTrackModuleLabel);
127 
128  // and the hits
129  art::FindManyP<recob::Hit> hitsSpill(trackHandle, evt, fTrackModuleLabel);
130 
131  // The outer loop is going to be over PFParticles
132  for (size_t pfPartIdx = 0; pfPartIdx != pfParticleHandle->size(); pfPartIdx++) {
133  art::Ptr<recob::PFParticle> pfParticle(pfParticleHandle, pfPartIdx);
134 
135  // Recover the track vector
136  std::vector<art::Ptr<recob::Track>> trackVec = pfPartToTrackAssns.at(pfPartIdx);
137 
138  // Is there a track associated to this PFParticle?
139  if (trackVec.empty()) {
140  // We need to make a null CosmicTag to store with this PFParticle to keep sequencing correct
141  std::vector<float> tempPt1, tempPt2;
142  tempPt1.push_back(-999);
143  tempPt1.push_back(-999);
144  tempPt1.push_back(-999);
145  tempPt2.push_back(-999);
146  tempPt2.push_back(-999);
147  tempPt2.push_back(-999);
148  cosmicTagTrackVector->emplace_back(tempPt1, tempPt2, 0., anab::CosmicTagID_t::kNotTagged);
149  util::CreateAssn(*this, evt, *cosmicTagTrackVector, pfParticle, *assnOutCosmicTagPFParticle);
150  continue;
151  }
152 
153  // Start the tagging process...
154  int isCosmic = 0;
156  art::Ptr<recob::Track> track1 = trackVec.front();
157 
158  std::vector<art::Ptr<recob::Hit>> hitVec = hitsSpill.at(track1.key());
159 
160  // Recover track end points
161  auto vertexPosition = track1->Vertex();
162  auto vertexDirection = track1->VertexDirection();
163  auto endPosition = track1->End();
164 
165  // In principle there is one track associated to a PFParticle... but with current
166  // technology it can happen that a PFParticle is broken into multiple tracks. Our
167  // aim here is to find the maximum extents of all the tracks which have been
168  // associated to the single PFParticle
169  if (trackVec.size() > 1) {
170  for (size_t trackIdx = 1; trackIdx < trackVec.size(); trackIdx++) {
171  art::Ptr<recob::Track> track(trackVec[trackIdx]);
172 
173  auto trackStart = track->Vertex();
174  auto trackEnd = track->End();
175 
176  // Arc length possibilities for start of track
177  double arcLStartToStart = (trackStart - vertexPosition).Dot(vertexDirection);
178  double arcLStartToEnd = (trackEnd - vertexPosition).Dot(vertexDirection);
179 
180  if (arcLStartToStart < 0. || arcLStartToEnd < 0.) {
181  if (arcLStartToStart < arcLStartToEnd)
182  vertexPosition = trackStart;
183  else
184  vertexPosition = trackEnd;
185  }
186 
187  // Arc length possibilities for end of track
188  double arcLEndToStart = (trackStart - endPosition).Dot(vertexDirection);
189  double arcLEndToEnd = (trackEnd - endPosition).Dot(vertexDirection);
190 
191  if (arcLEndToStart > 0. || arcLEndToEnd > 0.) {
192  if (arcLEndToStart > arcLEndToEnd)
193  endPosition = trackStart;
194  else
195  endPosition = trackEnd;
196  }
197 
198  // add the hits from this track to the collection
199  hitVec.insert(
200  hitVec.end(), hitsSpill.at(track.key()).begin(), hitsSpill.at(track.key()).end());
201  }
202  }
203 
204  // "Track" end points in easily readable form
205  float trackEndPt1_X = vertexPosition.X();
206  float trackEndPt1_Y = vertexPosition.Y();
207  float trackEndPt1_Z = vertexPosition.Z();
208  float trackEndPt2_X = endPosition.X();
209  float trackEndPt2_Y = endPosition.Y();
210  float trackEndPt2_Z = endPosition.Z();
211 
212  /////////////////////////////////////
213  // Check that all hits on particle are "in time"
214  /////////////////////////////////////
215  int nOutOfTime(0);
216 
217  for (unsigned int p = 0; p < hitVec.size(); p++) {
218  int peakLessRms = hitVec[p]->PeakTimeMinusRMS();
219  int peakPlusRms = hitVec[p]->PeakTimePlusRMS();
220 
221  if (peakLessRms < fMinTickDrift || peakPlusRms > fMaxTickDrift) {
222  if (++nOutOfTime > fMaxOutOfTime) {
223  isCosmic = 1;
225  break; // If one hit is out of time it must be a cosmic ray
226  }
227  }
228  }
229 
230  /////////////////////////////////
231  // Now check the TPC boundaries:
232  /////////////////////////////////
233  if (isCosmic == 0) {
234  // In below we check entry and exit points. Note that a special case of a particle entering
235  // and exiting the same surface is considered to be running parallel to the surface and NOT
236  // entering and exiting.
237  // Also, in what follows we make no assumptions on which end point is the "start" or
238  // "end" of the track being considered.
239  unsigned boundaryMask[] = {0, 0};
240 
241  // Check x extents - note that uboone coordinaes system has x=0 at edge
242  // Note this counts the case where the track enters and exits the same surface as a "1", not a "2"
243  // Also note that, in theory, any cosmic ray entering or exiting the X surfaces will have presumably
244  // been removed already by the checking of "out of time" hits... but this will at least label
245  // neutrino interaction tracks which exit through the X surfaces of the TPC
246  if (fDetWidth - trackEndPt1_X < fTPCXBoundary)
247  boundaryMask[0] = 0x1;
248  else if (trackEndPt1_X < fTPCXBoundary)
249  boundaryMask[0] = 0x2;
250 
251  if (fDetWidth - trackEndPt2_X < fTPCXBoundary)
252  boundaryMask[1] = 0x1;
253  else if (trackEndPt2_X < fTPCXBoundary)
254  boundaryMask[1] = 0x2;
255 
256  // Check y extents (note coordinate system change)
257  // Note this counts the case where the track enters and exits the same surface as a "1", not a "2"
258  if (fDetHalfHeight - trackEndPt1_Y < fTPCYBoundary)
259  boundaryMask[0] = 0x10;
260  else if (fDetHalfHeight + trackEndPt1_Y < fTPCYBoundary)
261  boundaryMask[0] = 0x20;
262 
263  if (fDetHalfHeight - trackEndPt2_Y < fTPCYBoundary)
264  boundaryMask[1] = 0x10;
265  else if (fDetHalfHeight + trackEndPt2_Y < fTPCYBoundary)
266  boundaryMask[1] = 0x20;
267 
268  // Check z extents
269  // Note this counts the case where the track enters and exits the same surface as a "1", not a "2"
270  if (fDetLength - trackEndPt1_Z < fTPCZBoundary)
271  boundaryMask[0] = 0x100;
272  else if (trackEndPt1_Z < fTPCZBoundary)
273  boundaryMask[0] = 0x200;
274 
275  if (fDetLength - trackEndPt2_Z < fTPCZBoundary)
276  boundaryMask[1] = 0x100;
277  else if (trackEndPt2_Z < fTPCZBoundary)
278  boundaryMask[1] = 0x200;
279 
280  unsigned trackMask = boundaryMask[0] | boundaryMask[1];
281  int nBitsSet(0);
282 
283  for (int idx = 0; idx < 12; idx++)
284  if (trackMask & (0x1 << idx)) nBitsSet++;
285 
286  // This should check for the case of a track which is both entering and exiting
287  // but we consider entering and exiting the z boundaries to be a special case (should it be?)
288  if (nBitsSet > 1) {
289  if ((trackMask & 0x300) != 0x300) {
290  isCosmic = 2;
291  if ((trackMask & 0x3) == 0x3)
293  else if ((trackMask & 0x30) == 0x30)
295  else if ((trackMask & 0x3) && (trackMask & 0x30))
297  else if ((trackMask & 0x3) && (trackMask & 0x300))
299  else
301  }
302  // This is the special case of track which appears to enter/exit z boundaries
303  else {
304  isCosmic = 3;
306  }
307  }
308  // This looks for track which enters/exits a boundary but has other endpoint in TPC
309  else if (nBitsSet > 0) {
310  isCosmic = 4;
311  if (trackMask & 0x3)
313  else if (trackMask & 0x30)
315  else if (trackMask & 0x300)
317  }
318  }
319 
320  std::vector<float> endPt1;
321  std::vector<float> endPt2;
322  endPt1.push_back(trackEndPt1_X);
323  endPt1.push_back(trackEndPt1_Y);
324  endPt1.push_back(trackEndPt1_Z);
325  endPt2.push_back(trackEndPt2_X);
326  endPt2.push_back(trackEndPt2_Y);
327  endPt2.push_back(trackEndPt2_Z);
328 
329  float cosmicScore = isCosmic > 0 ? 1. : 0.;
330 
331  // Handle special cases
332  if (isCosmic == 3)
333  cosmicScore = 0.4; // Enter/Exit at opposite Z boundaries
334  else if (isCosmic == 4)
335  cosmicScore = 0.5; // Enter or Exit but not both
336 
337  // Loop through the tracks resulting from this PFParticle and mark them
338  cosmicTagTrackVector->emplace_back(endPt1, endPt2, cosmicScore, tag_id);
339 
340  util::CreateAssn(*this, evt, *cosmicTagTrackVector, trackVec, *assnOutCosmicTagTrack);
341 
342  // Don't forget the association to the PFParticle
343  util::CreateAssn(*this, evt, *cosmicTagTrackVector, pfParticle, *assnOutCosmicTagPFParticle);
344  }
345 
346  evt.put(std::move(cosmicTagTrackVector));
347  evt.put(std::move(assnOutCosmicTagTrack));
348  evt.put(std::move(assnOutCosmicTagPFParticle));
349 
350 } // end of produce
351 
end
while True: pbar.update(maxval-len(onlies[E][S])) #print iS, "/", len(onlies[E][S]) found = False for...
std::string string
Definition: nybbler.cc:12
enum anab::cosmic_tag_id CosmicTagID_t
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
Vector_t VertexDirection() const
Definition: Track.h:132
art framework interface to geometry description
bool isValid() const noexcept
Definition: Handle.h:191
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Definition: DataViewImpl.h:633
const double e
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
def move(depos, offset)
Definition: depos.py:107
key_type key() const noexcept
Definition: Ptr.h:216
Point_t const & Vertex() const
Definition: Track.h:124
p
Definition: test.py:223
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
bool CreateAssn(PRODUCER const &prod, art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t indx=UINT_MAX)
Creates a single one-to-one association.
Declaration of signal hit object.
Provides recob::Track data product.
CosmicPFParticleTagger(fhicl::ParameterSet const &p)
Point_t const & End() const
Definition: Track.h:125
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:72
TCEvent evt
Definition: DataStructs.cxx:7
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
LArSoft geometry interface.
Definition: ChannelGeo.h:16
int fMaxOutOfTime
Max hits that can be out of time before rejecting.