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