LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
LArPandoraShowerAlg.cxx
Go to the documentation of this file.
3 
13 
15 #include "fhiclcpp/ParameterSet.h"
16 
17 #include "TCanvas.h"
18 #include "TH3.h"
19 #include "TPolyLine3D.h"
20 #include "TPolyMarker3D.h"
21 #include "TString.h"
22 #include "TStyle.h"
23 
24 #include <memory>
25 
27  : fUseCollectionOnly(pset.get<bool>("UseCollectionOnly"))
28  , fPFParticleLabel(pset.get<art::InputTag>("PFParticleLabel"))
29  , fSCEXFlip(pset.get<bool>("SCEXFlip"))
30  , fSCE(lar::providerFrom<spacecharge::SpaceChargeService>())
31  , fInitialTrackInputLabel(pset.get<std::string>("InitialTrackInputLabel"))
32  , fShowerStartPositionInputLabel(pset.get<std::string>("ShowerStartPositionInputLabel"))
33  , fShowerDirectionInputLabel(pset.get<std::string>("ShowerDirectionInputLabel"))
34  , fInitialTrackSpacePointsInputLabel(pset.get<std::string>("InitialTrackSpacePointsInputLabel"))
35 {}
36 
37 //Order the shower hits with regards to their projected length onto
38 //the shower direction from the shower start position. This is done
39 //in the 2D coordinate system (wire direction, x)
42  geo::Point_t const& ShowerStartPosition,
43  geo::Vector_t const& ShowerDirection) const
44 {
45  std::map<double, art::Ptr<recob::Hit>> OrderedHits;
46  art::Ptr<recob::Hit> startHit = hits.front();
47 
48  //Get the wireID
49  const geo::WireID startWireID = startHit->WireID();
50 
51  //Get the plane
52  const geo::PlaneID planeid = startWireID.asPlaneID();
53 
54  //Get the pitch
55  auto const& plane = fChannelMap->Plane(planeid);
56  double pitch = plane.WirePitch();
57 
58  TVector2 Shower2DStartPosition = {plane.WireCoordinate(ShowerStartPosition) * pitch,
59  ShowerStartPosition.X()};
60 
61  //Vector of the plane
62  auto const PlaneDirection = plane.GetIncreasingWireDirection();
63 
64  //get the shower 2D direction
65  TVector2 Shower2DDirection = {ShowerDirection.Dot(PlaneDirection), ShowerDirection.X()};
66 
67  Shower2DDirection = Shower2DDirection.Unit();
68 
69  for (auto const& hit : hits) {
70 
71  //Get the wireID
72  const geo::WireID WireID = hit->WireID();
73 
74  if (WireID.asPlaneID() != planeid) { break; }
75 
76  //Get the hit Vector.
77  TVector2 hitcoord = HitCoordinates(detProp, hit);
78 
79  //Order the hits based on the projection
80  TVector2 pos = hitcoord - Shower2DStartPosition;
81  OrderedHits[pos * Shower2DDirection] = hit;
82  }
83 
84  //Transform the shower.
85  std::vector<art::Ptr<recob::Hit>> showerHits;
86  std::transform(OrderedHits.begin(),
87  OrderedHits.end(),
88  std::back_inserter(showerHits),
89  [](std::pair<double, art::Ptr<recob::Hit>> const& hit) { return hit.second; });
90 
91  //Sometimes get the order wrong. Depends on direction compared to the plane Correct for it here:
92  art::Ptr<recob::Hit> frontHit = showerHits.front();
93  art::Ptr<recob::Hit> backHit = showerHits.back();
94 
95  //Get the hit Vector.
96  TVector2 fronthitcoord = HitCoordinates(detProp, frontHit);
97  TVector2 frontpos = fronthitcoord - Shower2DStartPosition;
98 
99  //Get the hit Vector.
100  TVector2 backhitcoord = HitCoordinates(detProp, backHit);
101  TVector2 backpos = backhitcoord - Shower2DStartPosition;
102 
103  double frontproj = frontpos * Shower2DDirection;
104  double backproj = backpos * Shower2DDirection;
105  if (std::abs(backproj) < std::abs(frontproj)) {
106  std::reverse(showerHits.begin(), showerHits.end());
107  }
108 
109  hits = showerHits;
110  return;
111 }
112 
113 //Orders the shower spacepoints with regards to there perpendicular distance from
114 //the shower axis.
117  geo::Point_t const& vertex,
118  geo::Vector_t const& direction) const
119 {
120 
121  std::map<double, art::Ptr<recob::SpacePoint>> OrderedSpacePoints;
122 
123  //Loop over the spacepoints and get the pojected distance from the vertex.
124  for (auto const& sp : showersps) {
125 
126  // Get the perpendicular distance
127  double perp = SpacePointPerpendicular(sp, vertex, direction);
128 
129  //Add to the list
130  OrderedSpacePoints[perp] = sp;
131  }
132 
133  //Return an ordered list.
134  showersps.clear();
135  for (auto const& sp : OrderedSpacePoints) {
136  showersps.push_back(sp.second);
137  }
138 }
139 
140 //Orders the shower spacepoints with regards to there prejected length from
141 //the shower start position in the shower direction.
144  geo::Point_t const& vertex,
145  geo::Vector_t const& direction) const
146 {
147 
148  std::map<double, art::Ptr<recob::SpacePoint>> OrderedSpacePoints;
149 
150  //Loop over the spacepoints and get the pojected distance from the vertex.
151  for (auto const& sp : showersps) {
152 
153  // Get the projection of the space point along the direction
154  double len = SpacePointProjection(sp, vertex, direction);
155 
156  //Add to the list
157  OrderedSpacePoints[len] = sp;
158  }
159 
160  //Return an ordered list.
161  showersps.clear();
162  for (auto const& sp : OrderedSpacePoints) {
163  showersps.push_back(sp.second);
164  }
165 }
166 
169  geo::Point_t const& vertex) const
170 {
171  std::map<double, art::Ptr<recob::SpacePoint>> OrderedSpacePoints;
172 
173  //Loop over the spacepoints and get the pojected distance from the vertex.
174  for (auto const& sp : showersps) {
175 
176  //Get the distance away from the start
177  double mag = (sp->position() - vertex).R();
178 
179  //Add to the list
180  OrderedSpacePoints[mag] = sp;
181  }
182 
183  //Return an ordered list.
184  showersps.clear();
185  for (auto const& sp : OrderedSpacePoints) {
186  showersps.push_back(sp.second);
187  }
188 }
189 
191  std::vector<art::Ptr<recob::SpacePoint>> const& showersps) const
192 {
193  if (showersps.empty()) return {};
194 
195  double x{};
196  double y{};
197  double z{};
198  for (auto const& sp : showersps) {
199  auto const pos = sp->position();
200  x += pos.X();
201  y += pos.Y();
202  z += pos.Z();
203  }
204  geo::Point_t centre_position{x, y, z};
205  centre_position *= (1. / showersps.size());
206  return centre_position;
207 }
208 
210  detinfo::DetectorClocksData const& clockData,
211  detinfo::DetectorPropertiesData const& detProp,
212  std::vector<art::Ptr<recob::SpacePoint>> const& showerspcs,
213  art::FindManyP<recob::Hit> const& fmh) const
214 {
215  float totalCharge = 0;
217  clockData, detProp, showerspcs, fmh, totalCharge);
218 }
219 
220 //Returns the vector to the shower centre and the total charge of the shower.
222  detinfo::DetectorClocksData const& clockData,
223  detinfo::DetectorPropertiesData const& detProp,
224  std::vector<art::Ptr<recob::SpacePoint>> const& showersps,
225  art::FindManyP<recob::Hit> const& fmh,
226  float& totalCharge) const
227 {
228  geo::Point_t chargePoint{};
229 
230  //Loop over the spacepoints and get the charge weighted center.
231  for (auto const& sp : showersps) {
232 
233  //Get the associated hits
234  std::vector<art::Ptr<recob::Hit>> const& hits = fmh.at(sp.key());
235 
236  //Average the charge unless sepcified.
237  float charge = 0;
238  float charge2 = 0;
239  for (auto const& hit : hits) {
240 
241  if (fUseCollectionOnly) {
242  if (hit->SignalType() == geo::kCollection) {
243  charge = hit->Integral();
244  //Correct for the lifetime: Need to do other detproperites
245  charge *= std::exp((sampling_rate(clockData) * hit->PeakTime()) /
246  (detProp.ElectronLifetime() * 1e3));
247  break;
248  }
249  }
250  else {
251 
252  //Correct for the lifetime FIX: Need to do other detproperties somehow
253  double Q = hit->Integral() * std::exp((sampling_rate(clockData) * hit->PeakTime()) /
254  (detProp.ElectronLifetime() * 1e3));
255 
256  charge += Q;
257  charge2 += Q * Q;
258  }
259  }
260 
261  if (!fUseCollectionOnly) {
262  //Calculate the unbiased standard deviation and mean.
263  float mean = charge / ((float)hits.size());
264 
265  float rms = 1;
266 
267  if (hits.size() > 1) {
268  rms = std::sqrt((charge2 - charge * charge) / ((float)(hits.size() - 1)));
269  }
270 
271  charge = 0;
272  int n = 0;
273  for (auto const& hit : hits) {
274  double lifetimecorrection = std::exp((sampling_rate(clockData) * hit->PeakTime()) /
275  (detProp.ElectronLifetime() * 1e3));
276  if (hit->Integral() * lifetimecorrection > (mean - 2 * rms) &&
277  hit->Integral() * lifetimecorrection < (mean + 2 * rms)) {
278  charge += hit->Integral() * lifetimecorrection;
279  ++n;
280  }
281  }
282 
283  if (n == 0) {
284  mf::LogWarning("LArPandoraShowerAlg") << "no points used to make the charge value. \n";
285  }
286 
287  charge /= n;
288  }
289 
290  //Get the position of the spacepoint
291  auto const pos = sp->position();
292  double const x = pos.X();
293  double const y = pos.Y();
294  double const z = pos.Z();
295 
296  chargePoint.SetXYZ(
297  chargePoint.X() + charge * x, chargePoint.Y() + charge * y, chargePoint.Z() + charge * z);
298  totalCharge += charge;
299 
300  if (charge == 0) {
301  mf::LogWarning("LArPandoraShowerAlg") << "Averaged charge, within 2 sigma, for a spacepoint "
302  "is zero, Maybe this not a good method. \n";
303  }
304  }
305 
306  double intotalcharge = 1 / totalCharge;
307  return chargePoint * intotalcharge;
308 }
309 
311  art::Ptr<recob::SpacePoint> const& sp_a,
312  art::Ptr<recob::SpacePoint> const& sp_b) const
313 {
314  return (sp_a->position() - sp_b->position()).R();
315 }
316 
317 //Return the charge of the spacepoint in ADC.
319  art::FindManyP<recob::Hit> const& fmh) const
320 {
321  double Charge = 0;
322 
323  //Average over the charge even though there is only one
324  std::vector<art::Ptr<recob::Hit>> const& hits = fmh.at(sp.key());
325  for (auto const& hit : hits) {
326  Charge += hit->Integral();
327  }
328 
329  Charge /= (float)hits.size();
330 
331  return Charge;
332 }
333 
334 //Return the spacepoint time.
336  art::FindManyP<recob::Hit> const& fmh) const
337 {
338  double Time = 0;
339 
340  //Average over the hits
341  std::vector<art::Ptr<recob::Hit>> const& hits = fmh.at(sp.key());
342  for (auto const& hit : hits) {
343  Time += hit->PeakTime();
344  }
345 
346  Time /= (float)hits.size();
347  return Time;
348 }
349 
350 //Return the cooordinates of the hit in cm in wire direction and x.
352  art::Ptr<recob::Hit> const& hit) const
353 {
354  //Get the pitch
355  const geo::WireID WireID = hit->WireID();
356  const geo::PlaneID planeid = WireID.asPlaneID();
357  double pitch = fChannelMap->Plane(planeid).WirePitch();
358 
359  return TVector2(WireID.Wire * pitch, detProp.ConvertTicksToX(hit->PeakTime(), planeid));
360 }
361 
363  geo::Point_t const& vertex,
364  geo::Vector_t const& direction) const
365 {
366  // Get the position of the spacepoint
367  auto const pos = sp->position() - vertex;
368 
369  // Get the the projected length
370  return pos.Dot(direction);
371 }
372 
374  geo::Point_t const& vertex,
375  geo::Vector_t const& direction) const
376 {
377  // Get the projection of the spacepoint
378  double proj = shower::LArPandoraShowerAlg::SpacePointProjection(sp, vertex, direction);
379 
380  return shower::LArPandoraShowerAlg::SpacePointPerpendicular(sp, vertex, direction, proj);
381 }
382 
384  geo::Point_t const& vertex,
385  geo::Vector_t const& direction,
386  double proj) const
387 {
388  // Get the position of the spacepoint
389  auto pos = sp->position() - vertex;
390 
391  // Take away the projection * distance to find the perpendicular vector
392  pos = pos - proj * direction;
393 
394  // Get the the projected length
395  return pos.R();
396 }
397 
398 //Function to calculate the RMS at segments of the shower and calculate the gradient of this. If negative then the direction is pointing the opposite way to the correct one
400  const geo::Point_t& ShowerCentre,
401  const geo::Vector_t& Direction,
402  const unsigned int nSegments) const
403 {
404  if (nSegments == 0)
405  throw cet::exception("LArPandoraShowerAlg")
406  << "Unable to calculate RMS Shower Gradient with 0 segments" << std::endl;
407 
408  if (sps.size() < 3) return 0;
409 
410  //Order the spacepoints
411  this->OrderShowerSpacePoints(sps, ShowerCentre, Direction);
412 
413  //Get the length of the shower.
414  const double minProj = this->SpacePointProjection(sps[0], ShowerCentre, Direction);
415  const double maxProj = this->SpacePointProjection(sps[sps.size() - 1], ShowerCentre, Direction);
416 
417  const double length = (maxProj - minProj);
418  const double segmentsize = length / nSegments;
419 
420  if (segmentsize < std::numeric_limits<double>::epsilon()) return 0;
421 
422  std::map<int, std::vector<float>> len_segment_map;
423 
424  //Split the the spacepoints into segments.
425  for (auto const& sp : sps) {
426 
427  //Get the the projected length
428  const double len = this->SpacePointProjection(sp, ShowerCentre, Direction);
429 
430  //Get the length to the projection
431  const double len_perp = this->SpacePointPerpendicular(sp, ShowerCentre, Direction, len);
432 
433  int sg_len = std::round(len / segmentsize);
434  len_segment_map[sg_len].push_back(len_perp);
435  }
436 
437  int counter = 0;
438  float sumx = 0.f;
439  float sumy = 0.f;
440  float sumx2 = 0.f;
441  float sumxy = 0.f;
442 
443  //Get the rms of the segments and caclulate the gradient.
444  for (auto const& segment : len_segment_map) {
445  if (segment.second.size() < 2) continue;
446  float RMS = this->CalculateRMS(segment.second);
447 
448  // Check if the calculation failed
449  if (RMS < 0) continue;
450 
451  //Calculate the gradient using regression
452  sumx += segment.first;
453  sumy += RMS;
454  sumx2 += segment.first * segment.first;
455  sumxy += RMS * segment.first;
456  ++counter;
457  }
458 
459  const float denom = counter * sumx2 - sumx * sumx;
460 
461  return std::abs(denom) < std::numeric_limits<float>::epsilon() ?
462  0 :
463  (counter * sumxy - sumx * sumy) / denom;
464 }
465 
466 double shower::LArPandoraShowerAlg::CalculateRMS(const std::vector<float>& perps) const
467 {
468 
469  if (perps.size() < 2) return std::numeric_limits<double>::lowest();
470 
471  float sum = 0;
472  for (const auto& perp : perps) {
473  sum += perp * perp;
474  }
475 
476  return std::sqrt(sum / (perps.size() - 1));
477 }
478 
480  geo::Point_t const& pos,
481  geo::Vector_t const& dir,
482  unsigned int const& TPC) const
483 {
484 
485  if (!fSCE || !fSCE->EnableCalSpatialSCE()) {
486  throw cet::exception("LArPandoraShowerALG")
487  << "Trying to correct SCE pitch when service is not configured" << std::endl;
488  }
489  // As the input pos is sce corrected already, find uncorrected pos
490  const geo::Point_t uncorrectedPos = pos + fSCE->GetPosOffsets(pos);
491  //Get the size of the correction at pos
492  const geo::Vector_t posOffset = fSCE->GetCalPosOffsets(uncorrectedPos, TPC);
493 
494  //Get the position of next hit
495  const geo::Point_t nextPos = uncorrectedPos + pitch * dir;
496  //Get the offsets at the next pos
497  const geo::Vector_t nextPosOffset = fSCE->GetCalPosOffsets(nextPos, TPC);
498 
499  //Calculate the corrected pitch
500  const int xFlip(fSCEXFlip ? -1 : 1);
501  geo::Vector_t pitchVec{pitch * dir.X() + xFlip * (nextPosOffset.X() - posOffset.X()),
502  pitch * dir.Y() + (nextPosOffset.Y() - posOffset.Y()),
503  pitch * dir.Z() + (nextPosOffset.Z() - posOffset.Z())};
504 
505  return pitchVec.r();
506 }
507 
509  geo::Point_t const& pos) const
510 {
511 
512  // Check the space charge service is properly configured
513  if (!fSCE || !fSCE->EnableSimEfieldSCE()) {
514  throw cet::exception("LArPandoraShowerALG")
515  << "Trying to correct SCE EField when service is not configured" << std::endl;
516  }
517  // Gets relative E field Distortions
518  geo::Vector_t EFieldOffsets = fSCE->GetEfieldOffsets(pos);
519  // Add 1 in X direction as this is the direction of the drift field
520  EFieldOffsets += geo::Vector_t{1, 0, 0};
521  // Convert to Absolute E Field from relative
522  EFieldOffsets *= EField;
523  // We only care about the magnitude for recombination
524  return EFieldOffsets.r();
525 }
526 
527 std::map<art::Ptr<recob::Hit>, std::vector<art::Ptr<recob::Hit>>>
529 {
530  // In this case, we need to only accept one hit in each snippet
531  // Snippets are counted by the Start, End, and Wire. If all these are the same for a hit, then they are on the same snippet.
532  //
533  // If there are multiple valid hits on the same snippet, we need a way to pick the best one.
534  // (TODO: find a good way). The current method is to take the one with the highest charge integral.
535  typedef std::pair<unsigned, std::vector<unsigned>> OrganizedHits;
536  struct HitIdentifier {
537  int startTick;
538  int endTick;
539  int wire;
540  float integral;
541 
542  // construct
543  explicit HitIdentifier(const recob::Hit& hit)
544  : startTick(hit.StartTick())
545  , endTick(hit.EndTick())
546  , wire(hit.WireID().Wire)
547  , integral(hit.Integral())
548  {}
549 
550  // Defines whether two hits are on the same snippet
551  inline bool operator==(const HitIdentifier& rhs) const
552  {
553  return startTick == rhs.startTick && endTick == rhs.endTick && wire == rhs.wire;
554  }
555 
556  // Defines which hit to pick between two both on the same snippet
557  inline bool operator>(const HitIdentifier& rhs) const { return integral > rhs.integral; }
558  };
559 
560  unsigned nplanes = 6; // TODO FIXME
561  std::vector<std::vector<OrganizedHits>> hits_org(nplanes);
562  std::vector<std::vector<HitIdentifier>> hit_idents(nplanes);
563  for (unsigned i = 0; i < hits.size(); i++) {
564  HitIdentifier this_ident(*hits[i]);
565 
566  // check if we have found a hit on this snippet before
567  bool found_snippet = false;
568  for (unsigned j = 0; j < hits_org[hits[i]->WireID().Plane].size(); j++) {
569  if (this_ident == hit_idents[hits[i]->WireID().Plane][j]) {
570  found_snippet = true;
571  if (this_ident > hit_idents[hits[i]->WireID().Plane][j]) {
572  hits_org[hits[i]->WireID().Plane][j].second.push_back(
573  hits_org[hits[i]->WireID().Plane][j].first);
574  hits_org[hits[i]->WireID().Plane][j].first = i;
575  hit_idents[hits[i]->WireID().Plane][j] = this_ident;
576  }
577  else {
578  hits_org[hits[i]->WireID().Plane][j].second.push_back(i);
579  }
580  break;
581  }
582  }
583  if (!found_snippet) {
584  hits_org[hits[i]->WireID().Plane].push_back({i, {}});
585  hit_idents[hits[i]->WireID().Plane].push_back(this_ident);
586  }
587  }
588  std::map<art::Ptr<recob::Hit>, std::vector<art::Ptr<recob::Hit>>> ret;
589  for (auto const& planeHits : hits_org) {
590  for (const OrganizedHits& hit_org : planeHits) {
591  std::vector<art::Ptr<recob::Hit>> secondaryHits{};
592  for (const unsigned secondaryID : hit_org.second) {
593  secondaryHits.push_back(hits[secondaryID]);
594  }
595  ret[hits[hit_org.first]] = std::move(secondaryHits);
596  }
597  }
598  return ret;
599 }
600 
602  art::Event const& Event,
603  reco::shower::ShowerElementHolder const& ShowerEleHolder,
604  std::string const& evd_disp_name_append) const
605 {
606 
607  std::cout << "Making Debug Event Display" << std::endl;
608 
609  //Function for drawing reco showers to check direction and initial track selection
610 
611  // Get run info to make unique canvas names
612  int run = Event.run();
613  int subRun = Event.subRun();
614  int event = Event.event();
615  int PFPID = pfparticle->Self();
616 
617  // Create the canvas
618  TString canvasName = Form("canvas_%i_%i_%i_%i", run, subRun, event, PFPID);
619  if (evd_disp_name_append.length() > 0) canvasName += "_" + evd_disp_name_append;
620  TCanvas* canvas = tfs->make<TCanvas>(canvasName, canvasName);
621 
622  // Initialise variables
623  double x = 0;
624  double y = 0;
625  double z = 0;
626 
627  double x_min = std::numeric_limits<double>::max(), x_max = -std::numeric_limits<double>::max();
628  double y_min = std::numeric_limits<double>::max(), y_max = -std::numeric_limits<double>::max();
629  double z_min = std::numeric_limits<double>::max(), z_max = -std::numeric_limits<double>::max();
630 
631  // Get a bunch of associations (again)
632  // N.B. this is a horribly inefficient way of doing things but as this is only
633  // going to be used to debug I don't care, I would rather have generality in this case
634 
635  auto const pfpHandle = Event.getValidHandle<std::vector<recob::PFParticle>>(fPFParticleLabel);
636 
637  // Get the spacepoint - PFParticle assn
638  art::FindManyP<recob::SpacePoint> fmspp(pfpHandle, Event, fPFParticleLabel);
639  if (!fmspp.isValid()) {
640  throw cet::exception("LArPandoraShowerAlg") << "Trying to get the spacepoint and failed. Somet\
641  hing is not configured correctly. Stopping ";
642  }
643 
644  // Get the SpacePoints
645  std::vector<art::Ptr<recob::SpacePoint>> const& spacePoints = fmspp.at(pfparticle.key());
646 
647  //We cannot progress with no spacepoints.
648  if (spacePoints.empty()) { return; }
649 
650  // Get info from shower property holder
651  geo::Point_t showerStartPosition = {-999, -999, -999};
652  geo::Vector_t showerDirection = {-999, -999, -999};
653  std::vector<art::Ptr<recob::SpacePoint>> trackSpacePoints;
654 
655  //######################
656  //### Start Position ###
657  //######################
658  double startXYZ[3] = {-999, -999, -999};
659  if (!ShowerEleHolder.CheckElement(fShowerStartPositionInputLabel)) {
660  mf::LogError("LArPandoraShowerAlg") << "Start position not set, returning " << std::endl;
661  // return;
662  }
663  else {
664  ShowerEleHolder.GetElement(fShowerStartPositionInputLabel, showerStartPosition);
665  // Create 3D point at vertex, chosed to be origin for ease of use of display
666  startXYZ[0] = showerStartPosition.X();
667  startXYZ[1] = showerStartPosition.Y();
668  startXYZ[2] = showerStartPosition.Z();
669  }
670  auto startPoly = std::make_unique<TPolyMarker3D>(1, startXYZ);
671 
672  //########################
673  //### Shower Direction ###
674  //########################
675 
676  double xDirPoints[2] = {-999, -999};
677  double yDirPoints[2] = {-999, -999};
678  double zDirPoints[2] = {-999, -999};
679 
680  //initialise counter point
681  int point = 0;
682 
683  // Make 3D points for each spacepoint in the shower
684  auto allPoly = std::make_unique<TPolyMarker3D>(spacePoints.size());
685 
686  if (!ShowerEleHolder.CheckElement(fShowerDirectionInputLabel) &&
687  !ShowerEleHolder.CheckElement("ShowerStartPosition")) {
688  mf::LogError("LArPandoraShowerAlg") << "Direction not set, returning " << std::endl;
689  }
690  else {
691 
692  // Get the min and max projections along the direction to know how long to draw
693  ShowerEleHolder.GetElement(fShowerDirectionInputLabel, showerDirection);
694 
695  // the direction line
696  double minProj = std::numeric_limits<double>::max();
697  double maxProj = -std::numeric_limits<double>::max();
698 
699  //initialise counter point
700  int point = 0;
701 
702  for (auto spacePoint : spacePoints) {
703  auto const pos = spacePoint->position();
704  x = pos.X();
705  y = pos.Y();
706  z = pos.Z();
707  allPoly->SetPoint(point, x, y, z);
708  ++point;
709 
710  x_min = std::min(x, x_min);
711  x_max = std::max(x, x_max);
712  y_min = std::min(y, y_min);
713  y_max = std::max(y, y_max);
714  z_min = std::min(z, z_min);
715  z_max = std::max(z, z_max);
716 
717  // Calculate the projection of (point-startpoint) along the direction
719  spacePoint, showerStartPosition, showerDirection);
720  maxProj = std::max(proj, maxProj);
721  minProj = std::min(proj, minProj);
722  } // loop over spacepoints
723 
724  xDirPoints[0] = (showerStartPosition.X() + minProj * showerDirection.X());
725  xDirPoints[1] = (showerStartPosition.X() + maxProj * showerDirection.X());
726 
727  yDirPoints[0] = (showerStartPosition.Y() + minProj * showerDirection.Y());
728  yDirPoints[1] = (showerStartPosition.Y() + maxProj * showerDirection.Y());
729 
730  zDirPoints[0] = (showerStartPosition.Z() + minProj * showerDirection.Z());
731  zDirPoints[1] = (showerStartPosition.Z() + maxProj * showerDirection.Z());
732  }
733 
734  auto dirPoly = std::make_unique<TPolyLine3D>(2, xDirPoints, yDirPoints, zDirPoints);
735 
736  //#########################
737  //### Initial Track SPs ###
738  //#########################
739 
740  auto trackPoly = std::make_unique<TPolyMarker3D>(trackSpacePoints.size());
741  if (!ShowerEleHolder.CheckElement(fInitialTrackSpacePointsInputLabel)) {
742  mf::LogError("LArPandoraShowerAlg") << "TrackSpacePoints not set, returning " << std::endl;
743  // return;
744  }
745  else {
746  ShowerEleHolder.GetElement(fInitialTrackSpacePointsInputLabel, trackSpacePoints);
747  point = 0; // re-initialise counter
748  for (auto spacePoint : trackSpacePoints) {
749  auto const pos = spacePoint->position();
750  x = pos.X();
751  y = pos.Y();
752  z = pos.Z();
753  trackPoly->SetPoint(point, x, y, z);
754  ++point;
755  x_min = std::min(x, x_min);
756  x_max = std::max(x, x_max);
757  y_min = std::min(y, y_min);
758  y_max = std::max(y, y_max);
759  z_min = std::min(z, z_min);
760  z_max = std::max(z, z_max);
761  } // loop over track spacepoints
762  }
763 
764  //#########################
765  //### Other PFParticles ###
766  //#########################
767 
768  // we want to draw all of the PFParticles in the event
769  //Get the PFParticles
770  std::vector<art::Ptr<recob::PFParticle>> pfps;
771  art::fill_ptr_vector(pfps, pfpHandle);
772 
773  // initialse counters
774  // Split into tracks and showers to make it clearer what pandora is doing
775  int pfpTrackCounter = 0;
776  int pfpShowerCounter = 0;
777 
778  // initial loop over pfps to find nuber of spacepoints for tracks and showers
779  for (auto const& pfp : pfps) {
780  std::vector<art::Ptr<recob::SpacePoint>> const& sps = fmspp.at(pfp.key());
781  // If running pandora cheating it will call photons pdg 22
782  int pdg = abs(pfp->PdgCode()); // Track or shower
783  if (pdg == 11 || pdg == 22) { pfpShowerCounter += sps.size(); }
784  else {
785  pfpTrackCounter += sps.size();
786  }
787  }
788 
789  auto pfpPolyTrack = std::make_unique<TPolyMarker3D>(pfpTrackCounter);
790  auto pfpPolyShower = std::make_unique<TPolyMarker3D>(pfpShowerCounter);
791 
792  // initialise counters
793  int trackPoints = 0;
794  int showerPoints = 0;
795 
796  for (auto const& pfp : pfps) {
797  std::vector<art::Ptr<recob::SpacePoint>> const& sps = fmspp.at(pfp.key());
798  int pdg = abs(pfp->PdgCode()); // Track or shower
799  for (auto const& sp : sps) {
800  auto const pos = sp->position();
801  x = pos.X();
802  y = pos.Y();
803  z = pos.Z();
804  x_min = std::min(x, x_min);
805  x_max = std::max(x, x_max);
806  y_min = std::min(y, y_min);
807  y_max = std::max(y, y_max);
808  z_min = std::min(z, z_min);
809  z_max = std::max(z, z_max);
810 
811  // If running pandora cheating it will call photons pdg 22
812  if (pdg == 11 || pdg == 22) {
813  pfpPolyShower->SetPoint(showerPoints, x, y, z);
814  ++showerPoints;
815  }
816  else {
817  pfpPolyTrack->SetPoint(trackPoints, x, y, z);
818  ++trackPoints;
819  }
820  } // loop over sps
821 
822  //pfpPolyTrack->Draw();
823 
824  } // if (fDrawAllPFPs)
825 
826  //#################################
827  //### Initial Track Traj Points ###
828  //#################################
829 
830  auto TrackTrajPoly = std::make_unique<TPolyMarker3D>(TPolyMarker3D(1));
831  auto TrackInitTrajPoly = std::make_unique<TPolyMarker3D>(TPolyMarker3D(1));
832 
833  if (ShowerEleHolder.CheckElement(fInitialTrackInputLabel)) {
834 
835  //Get the track
836  recob::Track InitialTrack;
837  ShowerEleHolder.GetElement(fInitialTrackInputLabel, InitialTrack);
838 
839  if (InitialTrack.NumberTrajectoryPoints() != 0) {
840 
841  point = 0;
842  // Make 3D points for each trajectory point in the track stub
843  for (unsigned int traj = 0; traj < InitialTrack.NumberTrajectoryPoints(); ++traj) {
844 
845  //ignore bogus info.
846  auto flags = InitialTrack.FlagsAtPoint(traj);
847  if (flags.isSet(recob::TrajectoryPointFlagTraits::NoPoint)) { continue; }
848 
849  geo::Point_t TrajPositionPoint = InitialTrack.LocationAtPoint(traj);
850  x = TrajPositionPoint.X();
851  y = TrajPositionPoint.Y();
852  z = TrajPositionPoint.Z();
853  TrackTrajPoly->SetPoint(point, x, y, z);
854  ++point;
855  } // loop over trajectory points
856 
857  geo::Point_t TrajInitPositionPoint = InitialTrack.LocationAtPoint(0);
858  x = TrajInitPositionPoint.X();
859  y = TrajInitPositionPoint.Y();
860  z = TrajInitPositionPoint.Z();
861  TrackInitTrajPoly->SetPoint(TrackInitTrajPoly->GetN(), x, y, z);
862  }
863  }
864 
865  gStyle->SetOptStat(0);
866  TH3F axes("axes", "", 1, x_min, x_max, 1, y_min, y_max, 1, z_min, z_max);
867  axes.SetDirectory(0);
868  axes.GetXaxis()->SetTitle("X");
869  axes.GetYaxis()->SetTitle("Y");
870  axes.GetZaxis()->SetTitle("Z");
871  axes.Draw();
872 
873  // Draw all of the things
874  pfpPolyShower->SetMarkerStyle(20);
875  pfpPolyShower->SetMarkerColor(4);
876  pfpPolyShower->Draw();
877  pfpPolyTrack->SetMarkerStyle(20);
878  pfpPolyTrack->SetMarkerColor(6);
879  pfpPolyTrack->Draw();
880  allPoly->SetMarkerStyle(20);
881  allPoly->Draw();
882  trackPoly->SetMarkerStyle(20);
883  trackPoly->SetMarkerColor(2);
884  trackPoly->Draw();
885  startPoly->SetMarkerStyle(21);
886  startPoly->SetMarkerSize(0.5);
887  startPoly->SetMarkerColor(3);
888  startPoly->Draw();
889  dirPoly->SetLineWidth(1);
890  dirPoly->SetLineColor(6);
891  dirPoly->Draw();
892  TrackTrajPoly->SetMarkerStyle(22);
893  TrackTrajPoly->SetMarkerColor(7);
894  TrackTrajPoly->Draw();
895  TrackInitTrajPoly->SetMarkerStyle(22);
896  TrackInitTrajPoly->SetMarkerColor(4);
897  TrackInitTrajPoly->Draw();
898 
899  // Save the canvas. Don't usually need this when using TFileService but this in the alg
900  // not a module and didn't work without this so im going with it.
901  canvas->Write();
902 }
Float_t x
Definition: compare.C:6
virtual bool EnableSimEfieldSCE() const =0
SubRunNumber_t subRun() const
Definition: Event.cc:35
double SCECorrectPitch(double const &pitch, geo::Point_t const &pos, geo::Vector_t const &dir, unsigned int const &TPC) const
double DistanceBetweenSpacePoints(art::Ptr< recob::SpacePoint > const &sp_a, art::Ptr< recob::SpacePoint > const &sp_b) const
void OrderShowerSpacePointsPerpendicular(std::vector< art::Ptr< recob::SpacePoint >> &showersps, geo::Point_t const &vertex, geo::Vector_t const &direction) const
Utilities related to art service access.
size_t Self() const
Returns the index of this particle.
Definition: PFParticle.h:88
void DebugEVD(art::Ptr< recob::PFParticle > const &pfparticle, art::Event const &Event, const reco::shower::ShowerElementHolder &ShowerEleHolder, std::string const &evd_disp_name_append="") const
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Definition: geo_vectors.h:160
static constexpr Flag_t NoPoint
The trajectory point is not defined.
double CalculateRMS(const std::vector< float > &perps) const
constexpr bool operator>(Interval< Q, Cat > const a, Quantity< Args... > const b) noexcept
Definition: intervals.h:507
T::provider_type const * providerFrom()
Returns a constant pointer to the provider of specified service.
Definition: ServiceUtil.h:75
virtual geo::Vector_t GetCalPosOffsets(geo::Point_t const &point, int const &TPCid) const =0
Declaration of signal hit object.
Float_t y
Definition: compare.C:6
Point_t const & LocationAtPoint(size_t i) const
Access to track position at different points.
Definition: Track.h:160
Double_t z
Definition: plot.C:276
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
geo::Point_t position() const
Returns the position of the point in world coordinates [cm].
Definition: SpacePoint.h:91
const std::string fInitialTrackInputLabel
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
Definition: Track.h:136
constexpr auto abs(T v)
Returns the absolute value of the argument.
STL namespace.
float Integral() const
Integral under the calibrated signal waveform of the hit, in tick x ADC units.
Definition: Hit.h:254
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:430
geo::WireID const & WireID() const
Initial tdc tick for hit.
Definition: Hit.h:290
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
double SpacePointTime(art::Ptr< recob::SpacePoint > const &sp, art::FindManyP< recob::Hit > const &fmh) const
double x_min
Definition: berger.C:15
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
LArPandoraShowerAlg(const fhicl::ParameterSet &pset)
geo::WireReadoutGeom const * fChannelMap
void hits()
Definition: readHits.C:15
double SpacePointPerpendicular(art::Ptr< recob::SpacePoint > const &sp, geo::Point_t const &vertex, geo::Vector_t const &direction) const
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
Definition: counter.h:292
virtual geo::Vector_t GetPosOffsets(geo::Point_t const &point) const =0
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
const std::string fInitialTrackSpacePointsInputLabel
key_type key() const noexcept
Definition: Ptr.h:166
std::map< art::Ptr< recob::Hit >, std::vector< art::Ptr< recob::Hit > > > OrganizeHits(const std::vector< art::Ptr< recob::Hit >> &hits) const
bool CheckElement(const std::string &Name) const
const std::string fShowerDirectionInputLabel
EventNumber_t event() const
Definition: Event.cc:41
int GetElement(const std::string &Name, T &Element) const
raw::TDCtick_t StartTick() const
Initial tdc tick for hit.
Definition: Hit.h:218
void OrderShowerHits(detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< recob::Hit >> &hits, geo::Point_t const &ShowerPosition, geo::Vector_t const &ShowerDirection) const
double SpacePointProjection(art::Ptr< recob::SpacePoint > const &sp, geo::Point_t const &vertex, geo::Vector_t const &direction) const
const std::string fShowerStartPositionInputLabel
Detector simulation of raw signals on wires.
double ConvertTicksToX(double ticks, int p, int t, int c) const
raw::TDCtick_t EndTick() const
Final tdc tick for hit.
Definition: Hit.h:222
double x_max
Definition: berger.C:16
double SpacePointCharge(art::Ptr< recob::SpacePoint > const &sp, art::FindManyP< recob::Hit > const &fmh) const
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
art::ServiceHandle< art::TFileService > tfs
virtual geo::Vector_t GetEfieldOffsets(geo::Point_t const &point) const =0
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
Definition: UtilFunc.cxx:13
float PeakTime() const
Time of the signal peak, in tick units.
Definition: Hit.h:226
virtual bool EnableCalSpatialSCE() const =0
ValidHandle< PROD > getValidHandle(InputTag const &tag) const
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
Definition: StdUtils.h:120
Encapsulate the construction of a single detector plane .
LArSoft-specific namespace.
Contains all timing reference information for the detector.
Provides recob::Track data product.
TDirectory * dir
Definition: macro.C:5
geo::Point_t ShowerCentre(std::vector< art::Ptr< recob::SpacePoint >> const &showersps) const
TVector2 HitCoordinates(detinfo::DetectorPropertiesData const &detProp, art::Ptr< recob::Hit > const &hit) const
void OrderShowerSpacePoints(std::vector< art::Ptr< recob::SpacePoint >> &showersps, geo::Point_t const &vertex, geo::Vector_t const &direction) const
Float_t proj
Definition: plot.C:35
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
Definition: MVAAlg.h:12
PointFlags_t const & FlagsAtPoint(size_t i) const
Access to i-th TrajectoryPoint or its Flags.
Definition: Track.h:152
double RMSShowerGradient(std::vector< art::Ptr< recob::SpacePoint >> &sps, const geo::Point_t &ShowerCentre, const geo::Vector_t &Direction, const unsigned int nSegments) const
Char_t n[5]
Direction
Definition: types.h:12
double SCECorrectEField(double const &EField, geo::Point_t const &pos) const
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:46
PlaneGeo const & Plane(TPCID const &tpcid, View_t view) const
Returns the specified wire.
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:306
Double_t sum
Definition: plot.C:31
RunNumber_t run() const
Definition: Event.cc:29
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
recob::tracking::Plane Plane
Definition: TrackState.h:17
spacecharge::SpaceCharge const * fSCE
bool operator==(infinite_endcount_iterator< T > const &, count_iterator< T > const &)
Definition: counter.h:277
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
Definition: Track.h:49
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
double WirePitch() const
Return the wire pitch (in centimeters). It is assumed constant.
Definition: PlaneGeo.h:312
Event finding and building.
Signal from collection planes.
Definition: geo_types.h:148
constexpr PlaneID const & asPlaneID() const
Conversion to WireID (for convenience of notation).
Definition: geo_types.h:466
vertex reconstruction