LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
RecoBaseDrawer.cxx
Go to the documentation of this file.
1 
5 #include <cmath>
6 #include <limits>
7 #include <map>
8 #include <stdint.h>
9 
10 #include "TBox.h"
11 #include "TH1.h"
12 #include "TLine.h"
13 #include "TMarker.h"
14 #include "TPolyLine.h"
15 #include "TPolyLine3D.h"
16 #include "TPolyMarker.h"
17 #include "TPolyMarker3D.h"
18 #include "TRotation.h"
19 #include "TText.h"
20 #include "TVector3.h"
21 
54 #include "larevt/CalibrationDBI/Interface/ChannelStatusProvider.h"
55 #include "larevt/CalibrationDBI/Interface/ChannelStatusService.h"
59 
67 #include "cetlib_except/exception.h"
69 
70 namespace {
71  // Utility function to make uniform error messages.
72  void writeErrMsg(const char* fcn, cet::exception const& e)
73  {
74  mf::LogWarning("RecoBaseDrawer") << "RecoBaseDrawer::" << fcn << " failed with message:\n" << e;
75  }
76 
77  auto const& getWireReadoutGeom()
78  {
80  }
81 } // namespace
82 
83 namespace evd {
84 
85  //......................................................................
87  {
89  auto const& wireReadoutGeom = getWireReadoutGeom();
92 
93  fWireMin.resize(0);
94  fWireMax.resize(0);
95  fTimeMin.resize(0);
96  fTimeMax.resize(0);
97  fRawCharge.resize(0);
98  fConvertedCharge.resize(0);
99 
100  // set the list of channels in this detector
101  for (auto const& tpcid : geo->Iterate<geo::TPCID>(geo::CryostatID{0})) {
102  unsigned int nplanes = wireReadoutGeom.Nplanes(tpcid);
103  fWireMin.resize(nplanes, -1);
104  fWireMax.resize(nplanes, -1);
105  fTimeMin.resize(nplanes, -1);
106  fTimeMax.resize(nplanes, -1);
107  fRawCharge.resize(nplanes, 0);
108  fConvertedCharge.resize(nplanes, 0);
109  for (auto const& plane : wireReadoutGeom.Iterate<geo::PlaneGeo>(tpcid)) {
110  auto const p = plane.ID().Plane;
111  fWireMin[p] = 0;
112  fWireMax[p] = plane.Nwires();
113  fTimeMin[p] = 0;
114  fTimeMax[p] = rawOptions->fTicks;
115  } // end loop over planes
116  } // end loop over TPCs
117 
119  art::make_tool<evdb_tool::ISpacePoints3D>(recoOptions->fAllSpacePointDrawerParams);
121  art::make_tool<evdb_tool::ISpacePoints3D>(recoOptions->fSpacePointDrawerParams);
122  }
123 
124  //......................................................................
126 
127  //......................................................................
128  void RecoBaseDrawer::Wire2D(const art::Event& evt, evdb::View2D* view, unsigned int plane)
129  {
133 
134  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
135 
136  lariov::ChannelStatusProvider const& channelStatus =
138 
139  int ticksPerPoint = rawOpt->fTicksPerPoint;
140 
141  // to make det independent later:
142  double mint = 5000;
143  double maxt = 0;
144  double minw = 5000;
145  double maxw = 0;
146 
147  geo::PlaneID pid(rawOpt->fCryostat, rawOpt->fTPC, plane);
148 
149  auto const& wireReadoutGeom = getWireReadoutGeom();
150  for (size_t imod = 0; imod < recoOpt->fWireLabels.size(); ++imod) {
151  art::InputTag const which = recoOpt->fWireLabels[imod];
152 
154  GetWires(evt, which, wires);
155 
156  if (wires.empty()) continue;
157 
158  for (size_t i = 0; i < wires.size(); ++i) {
159 
160  uint32_t channel = wires[i]->Channel();
161 
162  if (!rawOpt->fSeeBadChannels && channelStatus.IsBad(channel)) continue;
163 
164  std::vector<geo::WireID> wireids = wireReadoutGeom.ChannelToWire(channel);
165 
166  geo::SigType_t sigType = wireReadoutGeom.SignalType(channel);
167 
168  for (auto const& wid : wireids) {
169  if (wid.planeID() != pid) continue;
170 
171  double wire = 1. * wid.Wire;
172  double tick = 0;
173  // get the unpacked ROIs
174  std::vector<float> wirSig = wires[i]->Signal();
175  if (wirSig.size() == 0) continue;
176  // get an iterator over the adc values
177  std::vector<float>::const_iterator itr = wirSig.begin();
178  while (itr != wirSig.end()) {
179  int ticksUsed = 0;
180  double tdcsum = 0.;
181  double adcsum = 0.;
182  while (ticksUsed < ticksPerPoint && itr != wirSig.end()) {
183  tdcsum += tick;
184  adcsum += (1. * (*itr));
185  ++ticksUsed;
186  tick += 1.;
187  itr++; // this advance of the iterator is sufficient for the external loop too
188  }
189  double adc = adcsum / ticksPerPoint;
190  double tdc = tdcsum / ticksPerPoint;
191 
192  if (TMath::Abs(adc) < rawOpt->fMinSignal) continue;
193  if (tdc > rawOpt->fTicks) continue;
194 
195  int co = 0;
196  double sf = 1.;
197  double q0 = 1000.0;
198 
199  co = cst->CalQ(sigType).GetColor(adc);
200  if (rawOpt->fScaleDigitsByCharge) {
201  sf = sqrt(adc / q0);
202  if (sf > 1.0) sf = 1.0;
203  }
204 
205  if (wire < minw) minw = wire;
206  if (wire > maxw) maxw = wire;
207  if (tdc < mint) mint = tdc;
208  if (tdc > maxt) maxt = tdc;
209 
210  if (rawOpt->fAxisOrientation < 1) {
211  TBox& b1 = view->AddBox(wire - sf * 0.5,
212  tdc - sf * 0.5 * ticksPerPoint,
213  wire + sf * 0.5,
214  tdc + sf * 0.5 * ticksPerPoint);
215  b1.SetFillStyle(1001);
216  b1.SetFillColor(co);
217  b1.SetBit(kCannotPick);
218  }
219  else {
220  TBox& b1 = view->AddBox(tdc - sf * 0.5 * ticksPerPoint,
221  wire - sf * 0.5,
222  tdc + sf * 0.5 * ticksPerPoint,
223  wire + sf * 0.5);
224  b1.SetFillStyle(1001);
225  b1.SetFillColor(co);
226  b1.SetBit(kCannotPick);
227  }
228  } // end loop over samples
229  } //end loop over wire segments
230  } //end loop over wires
231  } // end loop over wire module labels
232 
233  fWireMin[plane] = minw;
234  fWireMax[plane] = maxw;
235  fTimeMin[plane] = mint;
236  fTimeMax[plane] = maxt;
237 
238  // Add a loop to draw dead wires in 2D display
239  double startTick(50.);
240  double endTick((rawOpt->fTicks - 50.) * ticksPerPoint);
241 
242  for (size_t wireNo = 0; wireNo < wireReadoutGeom.Nwires(pid); wireNo++) {
243  raw::ChannelID_t channel = wireReadoutGeom.PlaneWireToChannel(
244  geo::WireID(rawOpt->fCryostat, rawOpt->fTPC, plane, wireNo));
245 
246  if (!rawOpt->fSeeBadChannels && channelStatus.IsBad(channel)) {
247  double wire = 1. * wireNo;
248  TLine& line = view->AddLine(wire, startTick, wire, endTick);
249  line.SetLineColor(kGray);
250  line.SetLineWidth(1.0);
251  line.SetBit(kCannotPick);
252  }
253  }
254  }
255 
256  //......................................................................
265  detinfo::DetectorPropertiesData const& detProp,
266  evdb::View2D* view,
267  unsigned int plane)
268  {
271 
272  int nHitsDrawn(0);
273 
274  if (recoOpt->fDrawHits == 0) return nHitsDrawn;
275  if (rawOpt->fDrawRawDataOrCalibWires < 1) return nHitsDrawn;
276 
277  fRawCharge[plane] = 0;
278  fConvertedCharge[plane] = 0;
279 
280  auto const wire_pitch = getWireReadoutGeom().Plane({0, 0, 0}).WirePitch();
281  for (size_t imod = 0; imod < recoOpt->fHitLabels.size(); ++imod) {
282  art::InputTag const which = recoOpt->fHitLabels[imod];
283 
284  std::vector<const recob::Hit*> hits;
285  GetHits(evt, which, hits, plane);
286 
287  // Display all hits on the two 2D views provided
288  for (auto itr : hits) {
289 
290  if (itr->WireID().TPC != rawOpt->fTPC || itr->WireID().Cryostat != rawOpt->fCryostat)
291  continue;
292 
293  // Try to get the "best" charge measurement, ie. the one last in
294  // the calibration chain
295  fRawCharge[itr->WireID().Plane] += itr->PeakAmplitude();
296  double dQdX = itr->PeakAmplitude() / wire_pitch / detProp.ElectronsToADC();
297  fConvertedCharge[itr->WireID().Plane] += detProp.BirksCorrection(dQdX);
298  } // loop on hits
299 
300  nHitsDrawn = Hit2D(hits, kBlack, view, recoOpt->fDrawAllWireIDs);
301 
302  } // loop on imod folders
303 
304  return nHitsDrawn;
305  }
306 
307  //......................................................................
316  int RecoBaseDrawer::Hit2D(std::vector<const recob::Hit*> hits,
317  int color,
318  evdb::View2D* view,
319  bool allWireIDs,
320  bool drawConnectingLines,
321  int lineWidth)
322  {
325  auto const& wireReadoutGeom = getWireReadoutGeom();
326 
327  unsigned int w = 0;
328  unsigned int wold = 0;
329  float timeold = 0.;
330 
331  if (color == -1) color = recoOpt->fSelectedHitColor;
332 
333  int nHitsDrawn(0);
334 
335  for (const auto& hit : hits) {
336  // Note that the WireID in the hit object is useless for those detectors where a channel can correspond to
337  // more than one plane/wire. So our plan is to recover the list of wire IDs from the channel number and
338  // loop over those (if there are any)
339  // However, we need to preserve the option for drawing hits only associated to the wireID it contains
340  std::vector<geo::WireID> wireIDs;
341 
342  if (allWireIDs)
343  wireIDs = wireReadoutGeom.ChannelToWire(hit->Channel());
344  else
345  wireIDs.push_back(hit->WireID());
346 
347  // Loop to find match
348  for (const auto& wireID : wireIDs) {
349  if (wireID.TPC != rawOpt->fTPC || wireID.Cryostat != rawOpt->fCryostat) continue;
350 
351  if (std::isnan(hit->PeakTime()) || std::isnan(hit->Integral())) {
352  std::cout << "====>> Found hit with a NAN, channel: " << hit->Channel()
353  << ", start/end: " << hit->StartTick() << "/" << hit->EndTick()
354  << ", chisquare: " << hit->GoodnessOfFit() << std::endl;
355  }
356 
357  if (hit->PeakTime() > rawOpt->fTicks) continue;
358 
359  w = wireID.Wire;
360 
361  // Try to get the "best" charge measurement, ie. the one last in
362  // the calibration chain
363  float time = hit->PeakTime();
364  float rms = 0.5 * hit->RMS();
365 
366  if (rawOpt->fAxisOrientation < 1) {
367  TBox& b1 = view->AddBox(w - 0.5, time - rms, w + 0.5, time + rms);
368  if (drawConnectingLines && nHitsDrawn > 0) {
369  TLine& l = view->AddLine(w, time, wold, timeold);
370  l.SetLineColor(color);
371  l.SetBit(kCannotPick);
372  }
373  b1.SetFillStyle(0);
374  b1.SetBit(kCannotPick);
375  b1.SetLineColor(color);
376  b1.SetLineWidth(lineWidth);
377  }
378  else {
379  TBox& b1 = view->AddBox(time - rms, w - 0.5, time + rms, w + 0.5);
380  if (drawConnectingLines && nHitsDrawn > 0) {
381  TLine& l = view->AddLine(time, w, timeold, wold);
382  l.SetLineColor(color);
383  l.SetBit(kCannotPick);
384  }
385  b1.SetFillStyle(0);
386  b1.SetBit(kCannotPick);
387  b1.SetLineColor(color);
388  b1.SetLineWidth(lineWidth);
389  }
390  wold = w;
391  timeold = time;
392  nHitsDrawn++;
393  }
394  } // loop on hits
395 
396  return nHitsDrawn;
397  }
398 
399  //........................................................................
400  int RecoBaseDrawer::Hit2D(std::vector<const recob::Hit*> hits,
401  evdb::View2D* view,
402  float cosmicscore)
403  {
407 
408  unsigned int w(0);
409  unsigned int wold(0);
410  float timeold(0.);
411  int nHitsDrawn(0);
412 
413  for (const auto& hit : hits) {
414  // check that we are in the correct TPC
415  // the view should tell use we are in the correct plane
416  if (hit->WireID().TPC != rawOpt->fTPC || hit->WireID().Cryostat != rawOpt->fCryostat)
417  continue;
418 
419  w = hit->WireID().Wire;
420 
421  // Try to get the "best" charge measurement, ie. the one last in
422  // the calibration chain
423  float time = hit->PeakTime();
424 
425  if (rawOpt->fAxisOrientation < 1) {
426  if (nHitsDrawn > 0) {
427  TLine& l = view->AddLine(w, time + 100, wold, timeold + 100);
428  l.SetLineWidth(3);
429  l.SetLineColor(1);
430  if (cosmicscore > 0.5) l.SetLineColor(kMagenta);
431  l.SetBit(kCannotPick);
432  }
433  }
434  else {
435  if (nHitsDrawn > 0) {
436  TLine& l = view->AddLine(time + 20, w, timeold + 20, wold);
437  l.SetLineColor(1);
438  if (cosmicscore > 0.5) l.SetLineStyle(2);
439  l.SetBit(kCannotPick);
440  }
441  }
442 
443  wold = w;
444  timeold = time;
445  nHitsDrawn++;
446  } // loop on hits
447 
448  return nHitsDrawn;
449  }
450 
451  //........................................................................
452  int RecoBaseDrawer::GetRegionOfInterest(int plane, int& minw, int& maxw, int& mint, int& maxt)
453  {
456 
457  if ((unsigned int)plane > fWireMin.size()) {
458  mf::LogWarning("RecoBaseDrawer")
459  << " Requested plane " << plane << " is larger than those available ";
460  return -1;
461  }
462 
463  minw = fWireMin[plane];
464  maxw = fWireMax[plane];
465  mint = fTimeMin[plane];
466  maxt = fTimeMax[plane];
467 
468  //make values a bit larger, but make sure they don't go out of bounds
469  minw = (minw - 30 < 0) ? 0 : minw - 30;
470  mint = (mint - 10 < 0) ? 0 : mint - 10;
471 
472  int fTicks = rawOpt->fTicks;
473 
474  geo::PlaneID const planeid(0, 0, plane);
475  maxw = std::min(maxw + 10, (int)getWireReadoutGeom().Nwires(planeid));
476  maxt = (maxt + 10 > fTicks) ? fTicks : maxt + 10;
477 
478  return 0;
479  }
480 
481  //......................................................................
482  void RecoBaseDrawer::GetChargeSum(int plane, double& charge, double& convcharge)
483  {
484  charge = fRawCharge[plane];
485  convcharge = fConvertedCharge[plane];
486 
487  return;
488  }
489 
490  //......................................................................
491  void RecoBaseDrawer::EndPoint2D(const art::Event& evt, evdb::View2D* view, unsigned int plane)
492  {
495 
496  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
497  if (recoOpt->fDraw2DEndPoints == 0) return;
498 
499  geo::PlaneID const planeid{0, rawOpt->fTPC, plane};
500  geo::View_t gview = getWireReadoutGeom().Plane(planeid).View();
501 
502  for (size_t imod = 0; imod < recoOpt->fEndPoint2DLabels.size(); ++imod) {
503  art::InputTag const which = recoOpt->fEndPoint2DLabels[imod];
504 
506  GetEndPoint2D(evt, which, ep2d);
507 
508  for (size_t iep = 0; iep < ep2d.size(); ++iep) {
509  // only worry about end points with the correct view
510  if (ep2d[iep]->View() != gview) continue;
511 
513  // need to be sure that all EndPoint2D objects have filled the required information
514 
515  // draw cluster with unique marker
516  // Place this cluster's unique marker at the hit's location
517  int color = evd::kColor[ep2d[iep]->ID() % evd::kNCOLS];
518 
519  double x = ep2d[iep]->WireID().Wire;
520  double y = ep2d[iep]->DriftTime();
521 
522  if (rawOpt->fAxisOrientation > 0) {
523  x = ep2d[iep]->DriftTime();
524  y = ep2d[iep]->WireID().Wire;
525  }
526 
527  TMarker& strt = view->AddMarker(x, y, color, 30, 2.0);
528  strt.SetMarkerColor(color);
529  // BB: draw the ID
530  if (recoOpt->fDraw2DEndPoints > 1) {
531  std::string s = "2V" + std::to_string(ep2d[iep]->ID());
532  char const* txt = s.c_str();
533  TText& vtxID = view->AddText(x, y + 20, txt);
534  vtxID.SetTextColor(color);
535  vtxID.SetTextSize(0.05);
536  }
537 
538  } // loop on iep end points
539  } // loop on imod folders
540 
541  return;
542  }
543 
544  //......................................................................
546  detinfo::DetectorClocksData const& clockData,
547  detinfo::DetectorPropertiesData const& detProp,
548  evdb::View2D* view,
549  unsigned int plane)
550  {
553 
554  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
555  if (recoOpt->fDrawOpFlashes == 0) return;
556 
557  geo::PlaneID pid(rawOpt->fCryostat, rawOpt->fTPC, plane);
558  auto const& planeg = getWireReadoutGeom().Plane(pid);
559 
560  for (size_t imod = 0; imod < recoOpt->fOpFlashLabels.size(); ++imod) {
561  const art::InputTag which = recoOpt->fOpFlashLabels[imod];
562 
564  GetOpFlashes(evt, which, opflashes);
565 
566  if (opflashes.size() < 1) continue;
567 
568  int NFlashes = opflashes.size();
569  //double TopCoord = 1000;
570 
571  MF_LOG_VERBATIM("RecoBaseDrawer") << "Total " << NFlashes << " flashes.";
572 
573  // project each seed into this view
574  for (size_t iof = 0; iof < opflashes.size(); ++iof) {
575  if (opflashes[iof]->TotalPE() < recoOpt->fFlashMinPE) continue;
576  if (opflashes[iof]->Time() < recoOpt->fFlashTMin) continue;
577  if (opflashes[iof]->Time() > recoOpt->fFlashTMax) continue;
578  int Color = evd::kColor[(iof) % evd::kNCOLS];
579  MF_LOG_VERBATIM("RecoBaseDrawer")
580  << "Flash t: " << opflashes[iof]->Time() << "\t y,z : " << opflashes[iof]->YCenter()
581  << ", " << opflashes[iof]->ZCenter() << " \t PE :" << opflashes[iof]->TotalPE();
582 
583  float flashtick =
584  opflashes[iof]->Time() / sampling_rate(clockData) * 1e3 + detProp.GetXTicksOffset(pid);
585  float wire0 = FLT_MAX;
586  float wire1 = FLT_MIN;
587 
588  //Find the 4 corners and convert them to wire numbers
589  std::vector<geo::Point_t> points;
590  points.emplace_back(0,
591  opflashes[iof]->YCenter() - opflashes[iof]->YWidth(),
592  opflashes[iof]->ZCenter() - opflashes[iof]->ZWidth());
593  points.emplace_back(0,
594  opflashes[iof]->YCenter() - opflashes[iof]->YWidth(),
595  opflashes[iof]->ZCenter() + opflashes[iof]->ZWidth());
596  points.emplace_back(0,
597  opflashes[iof]->YCenter() + opflashes[iof]->YWidth(),
598  opflashes[iof]->ZCenter() - opflashes[iof]->ZWidth());
599  points.emplace_back(0,
600  opflashes[iof]->YCenter() + opflashes[iof]->YWidth(),
601  opflashes[iof]->ZCenter() + opflashes[iof]->ZWidth());
602 
603  for (size_t i = 0; i < points.size(); ++i) {
604  geo::WireID wireID;
605  try {
606  wireID = planeg.NearestWireID(points[i]);
607  }
608  catch (geo::InvalidWireError const& e) {
609  wireID = e.suggestedWireID(); // pick the closest valid wire
610  }
611  if (wireID.Wire < wire0) wire0 = wireID.Wire;
612  if (wireID.Wire > wire1) wire1 = wireID.Wire;
613  }
614  if (rawOpt->fAxisOrientation > 0) {
615  TLine& line = view->AddLine(flashtick, wire0, flashtick, wire1);
616  line.SetLineWidth(2);
617  line.SetLineStyle(2);
618  line.SetLineColor(Color);
619  }
620  else {
621  TLine& line = view->AddLine(wire0, flashtick, wire1, flashtick);
622  line.SetLineWidth(2);
623  line.SetLineStyle(2);
624  line.SetLineColor(Color);
625  }
626  } // loop on opflashes
627  } // loop on imod folders
628  }
629 
630  //......................................................................
632  detinfo::DetectorPropertiesData const& detProp,
633  evdb::View2D* view,
634  unsigned int plane)
635  {
638 
639  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
640  if (recoOpt->fDrawSeeds == 0) return;
641 
642  geo::PlaneID const planeID{rawOpt->fCryostat, rawOpt->fTPC, plane};
643  auto const& planeg = getWireReadoutGeom().Plane(planeID);
644 
645  for (size_t imod = 0; imod < recoOpt->fSeedLabels.size(); ++imod) {
646  art::InputTag const which = recoOpt->fSeedLabels[imod];
647 
649  GetSeeds(evt, which, seeds);
650 
651  if (seeds.size() < 1) continue;
652 
653  // project each seed into this view
654  for (size_t isd = 0; isd < seeds.size(); ++isd) {
655  double SeedPoint[3];
656  double SeedDir[3];
657  double SeedPointErr[3];
658  double SeedDirErr[3];
659  double SeedEnd1[3];
660  double SeedEnd2[3];
661 
662  seeds[isd]->GetPoint(SeedPoint, SeedPointErr);
663  seeds[isd]->GetDirection(SeedDir, SeedDirErr);
664 
665  SeedEnd1[0] = SeedPoint[0] + SeedDir[0];
666  SeedEnd1[1] = SeedPoint[1] + SeedDir[1];
667  SeedEnd1[2] = SeedPoint[2] + SeedDir[2];
668 
669  SeedEnd2[0] = SeedPoint[0] - SeedDir[0];
670  SeedEnd2[1] = SeedPoint[1] - SeedDir[1];
671  SeedEnd2[2] = SeedPoint[2] - SeedDir[2];
672 
673  // Draw seed on evd
674  // int color = kColor[seeds[isd]->ID()%kNCOLS];
675  int color = evd::kColor[0];
676  unsigned int wirepoint = 0;
677  unsigned int wireend1 = 0;
678  unsigned int wireend2 = 0;
679  using geo::vect::toPoint;
680  try {
681  wirepoint = planeg.NearestWireID(toPoint(SeedPoint)).Wire;
682  }
683  catch (cet::exception& e) {
684  wirepoint = atoi(e.explain_self().substr(e.explain_self().find("#") + 1, 5).c_str());
685  }
686  try {
687  wireend1 = planeg.NearestWireID(toPoint(SeedEnd1)).Wire;
688  }
689  catch (cet::exception& e) {
690  wireend1 = atoi(e.explain_self().substr(e.explain_self().find("#") + 1, 5).c_str());
691  }
692  try {
693  wireend2 = planeg.NearestWireID(toPoint(SeedEnd2)).Wire;
694  }
695  catch (cet::exception& e) {
696  wireend2 = atoi(e.explain_self().substr(e.explain_self().find("#") + 1, 5).c_str());
697  }
698 
699  double x = wirepoint;
700  double y = detProp.ConvertXToTicks(SeedPoint[0], planeID);
701  double x1 = wireend1;
702  double y1 = detProp.ConvertXToTicks(SeedEnd1[0], planeID);
703  double x2 = wireend2;
704  double y2 = detProp.ConvertXToTicks(SeedEnd2[0], planeID);
705 
706  if (rawOpt->fAxisOrientation > 0) {
707  x = detProp.ConvertXToTicks(SeedPoint[0], planeID);
708  y = wirepoint;
709  x1 = detProp.ConvertXToTicks(SeedEnd1[0], planeID);
710  y1 = wireend1;
711  x2 = detProp.ConvertXToTicks(SeedEnd2[0], planeID);
712  y2 = wireend2;
713  }
714 
715  TMarker& strt = view->AddMarker(x, y, color, 4, 1.5);
716  TLine& line = view->AddLine(x1, y1, x2, y2);
717  strt.SetMarkerColor(color);
718  line.SetLineColor(color);
719  line.SetLineWidth(2.0);
720  } // loop on seeds
721  } // loop on imod folders
722  }
723 
724  //......................................................................
726  detinfo::DetectorPropertiesData const& detProp,
727  evdb::View2D* view,
728  unsigned int plane)
729  {
730  // Color code hits associated with Slices
733  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
734  if (recoOpt->fDrawSlices == 0) return;
735 
736  static bool first = true;
737  if (first) {
738  std::cout
739  << "******** DrawSlices: 0 = none, 1 = color coded, 2 = color coded + ID at slice center\n";
740  std::cout << " 3 = open circle at slice center with size proportional to the AspectRatio. "
741  "Closed circles";
742  std::cout << " at the slice ends with connecting dotted lines\n";
743  first = false;
744  }
745  unsigned int c = rawOpt->fCryostat;
746  unsigned int t = rawOpt->fTPC;
747  geo::PlaneID planeID(c, t, plane);
748  auto const& planeg = getWireReadoutGeom().Plane(planeID);
749 
750  for (size_t imod = 0; imod < recoOpt->fSliceLabels.size(); ++imod) {
751  art::InputTag const which = recoOpt->fSliceLabels[imod];
753  GetSlices(evt, which, slices);
754  if (slices.size() < 1) continue;
755  art::FindMany<recob::Hit> fmh(slices, evt, which);
756  for (size_t isl = 0; isl < slices.size(); ++isl) {
757  int slcID(std::abs(slices[isl]->ID()));
758  int color(evd::kColor[slcID % evd::kNCOLS]);
759  if (recoOpt->fDrawSlices < 3) {
760  // draw color-coded hits
761  std::vector<const recob::Hit*> hits = fmh.at(isl);
762  std::vector<const recob::Hit*> hits_on_plane;
763  for (auto hit : hits) {
764  if (hit->WireID().Plane == plane) { hits_on_plane.push_back(hit); }
765  }
766  if (Hit2D(hits_on_plane, color, view, false, false) < 1) continue;
767  if (recoOpt->fDrawSlices == 2) {
768  geo::Point_t slicePos(
769  slices[isl]->Center().X(), slices[isl]->Center().Y(), slices[isl]->Center().Z());
770  double tick = detProp.ConvertXToTicks(slices[isl]->Center().X(), planeID);
771  double wire = planeg.WireCoordinate(slicePos);
772  std::string s = std::to_string(slcID);
773  char const* txt = s.c_str();
774  TText& slcID = view->AddText(wire, tick, txt);
775  slcID.SetTextSize(0.05);
776  slcID.SetTextColor(color);
777  } // draw ID
778  }
779  else {
780  // draw the center, end points and direction vector
781  geo::Point_t slicePos(
782  slices[isl]->Center().X(), slices[isl]->Center().Y(), slices[isl]->Center().Z());
783  double tick = detProp.ConvertXToTicks(slices[isl]->Center().X(), planeID);
784  double wire = planeg.WireCoordinate(slicePos);
785  float markerSize = 1;
786  if (slices[isl]->AspectRatio() > 0) {
787  markerSize = 1 / slices[isl]->AspectRatio();
788  if (markerSize > 3) markerSize = 3;
789  }
790  TMarker& ctr = view->AddMarker(wire, tick, color, 24, markerSize);
791  ctr.SetMarkerColor(color);
792  // npts, color, width, style
793  TPolyLine& pline = view->AddPolyLine(2, color, 2, 3);
794  geo::Point_t slicePos0(
795  slices[isl]->End0Pos().X(), slices[isl]->End0Pos().Y(), slices[isl]->End0Pos().Z());
796  tick = detProp.ConvertXToTicks(slices[isl]->End0Pos().X(), planeID);
797  wire = planeg.WireCoordinate(slicePos0);
798  TMarker& end0 = view->AddMarker(wire, tick, color, 20, 1.0);
799  end0.SetMarkerColor(color);
800  pline.SetPoint(0, wire, tick);
801  geo::Point_t slicePos1(
802  slices[isl]->End1Pos().X(), slices[isl]->End1Pos().Y(), slices[isl]->End1Pos().Z());
803  tick = detProp.ConvertXToTicks(slices[isl]->End1Pos().X(), plane, t, c);
804  wire = planeg.WireCoordinate(slicePos1);
805  TMarker& end1 = view->AddMarker(wire, tick, color, 20, 1.0);
806  end1.SetMarkerColor(color);
807  pline.SetPoint(1, wire, tick);
808  }
809  } // isl
810  } // imod
811  } // Slice2D
812 
813  //......................................................................
815  detinfo::DetectorClocksData const& clockData,
816  detinfo::DetectorPropertiesData const& detProp,
817  evdb::View2D* view,
818  unsigned int plane)
819  {
822 
823  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
824  if (recoOpt->fDrawClusters == 0) return;
825 
826  geo::PlaneID const planeid{0, rawOpt->fTPC, plane};
827  auto const& planeg = getWireReadoutGeom().Plane(planeid);
828 
829  // if user sets "DrawClusters" to 2, draw the clusters differently:
830  bool drawAsMarkers = recoOpt->fDrawClusters != 2;
831 
832  // draw connecting lines between cluster hits?
833  bool drawConnectingLines = (recoOpt->fDrawClusters >= 3);
834 
835  static bool first = true;
836  if (first) {
837  std::cout << "******** DrawClusters: 0 = none, 1 = cluster hits, 2 = unique marker, 3 = "
838  "cluster hits with connecting lines.\n";
839  std::cout << " 4 = with T<cluster or trajectory ID> P<PFParticle ID> color-matched. "
840  "Unmatched cluster IDs shown in black.\n";
841  std::cout << " Color scheme: By cluster ID in each plane or by PFParticle ID (Self) if a "
842  "PFParticle - Cluster association exists.\n";
843  first = false;
844  }
845 
846  for (size_t imod = 0; imod < recoOpt->fClusterLabels.size(); ++imod) {
847  art::InputTag const which = recoOpt->fClusterLabels[imod];
848 
850  GetClusters(evt, which, clust);
851 
852  if (clust.size() < 1) continue;
853 
854  // We want to draw the hits that are associated to "free" space points (non clustered)
855  // This is done here, before drawing the hits on clusters so they will be "under" the cluster
856  // hits (since spacepoints could be made from a used 2D hit but then not used themselves)
857  // Get the space points created by the PFParticle producer
858  std::vector<art::Ptr<recob::SpacePoint>> spacePointVec;
859  GetSpacePoints(evt, which, spacePointVec);
860 
861  // No space points no continue
862  if (spacePointVec.size() > 0) {
863  // Add the relations to recover associations cluster hits
864  art::FindManyP<recob::Hit> spHitAssnVec(spacePointVec, evt, which);
865 
866  if (spHitAssnVec.isValid()) {
867  // Create a local hit vector...
868  std::vector<const recob::Hit*> freeHitVec;
869 
870  // loop through space points looking for those that are free
871  for (const auto& spacePointPtr : spacePointVec) {
872  if (spacePointPtr->Chisq() < -99.) {
873  // Recover associated hits
874  const std::vector<art::Ptr<recob::Hit>>& hitVec =
875  spHitAssnVec.at(spacePointPtr.key());
876 
877  for (const auto& hitPtr : hitVec) {
878  if (hitPtr.get()->WireID().Plane != plane) continue;
879 
880  freeHitVec.push_back(hitPtr.get());
881  }
882  }
883  }
884 
885  // Draw the free hits in gray
886  Hit2D(freeHitVec, kGray, view, false, false, false);
887  }
888  }
889 
890  // Ok, now proceed with our normal processing of hits on clusters
891  art::FindMany<recob::Hit> fmh(clust, evt, which);
892  art::FindManyP<recob::PFParticle> fmc(clust, evt, which);
893 
894  for (size_t ic = 0; ic < clust.size(); ++ic) {
895  if (clust[ic]->Plane().Plane != plane) continue;
896 
897  // see if we can set the color index in a sensible fashion
898  int clusterIdx(std::abs(clust[ic]->ID()));
899  int colorIdx(clusterIdx % evd::kNCOLS);
900  bool pfpAssociation = false;
901  int pfpIndex = INT_MAX;
902  float cosmicscore = FLT_MIN;
903 
904  if (fmc.isValid()) {
905  std::vector<art::Ptr<recob::PFParticle>> pfplist = fmc.at(ic);
906  // Use the first one
907  if (!pfplist.empty()) {
908  clusterIdx = pfplist[0]->Self();
909  colorIdx = clusterIdx % evd::kNCOLS;
910  pfpAssociation = true;
911  pfpIndex = pfplist[0]->Self();
912  //Get cosmic score
913  if (recoOpt->fDrawCosmicTags) {
914  art::FindManyP<anab::CosmicTag> fmct(pfplist, evt, which);
915  if (fmct.isValid()) {
916  std::vector<art::Ptr<anab::CosmicTag>> ctlist = fmct.at(0);
917  if (!ctlist.empty()) { cosmicscore = ctlist[0]->CosmicScore(); }
918  }
919  }
920  } // pfplist is not empty
921  }
922 
923  std::vector<const recob::Hit*> hits = fmh.at(ic);
924 
925  if (drawAsMarkers) {
926  // draw cluster with unique marker
927  // Place this cluster's unique marker at the hit's location
928  int color = evd::kColor[colorIdx];
929 
930  // If there are no hits in this cryostat/TPC then we skip the rest
931  // That no hits were drawn is the sign for this
932  if (Hit2D(hits, color, view, false, drawConnectingLines) < 1) continue;
933 
934  if (recoOpt->fDrawCosmicTags && cosmicscore != FLT_MIN) Hit2D(hits, view, cosmicscore);
935 
936  if (recoOpt->fDrawClusters > 3) {
937  // Put a T in front to denote a trajectory ID
938  std::string s = "T" + std::to_string(clust[ic]->ID());
939  // append the PFP index + 1 (sort of the ID)
940  if (pfpIndex != INT_MAX) s = s + " P" + std::to_string(pfpIndex + 1);
941  char const* txt = s.c_str();
942  double wire = 0.5 * (clust[ic]->StartWire() + clust[ic]->EndWire());
943  double tick = 20 + 0.5 * (clust[ic]->StartTick() + clust[ic]->EndTick());
944  TText& clID = view->AddText(wire, tick, txt);
945  clID.SetTextSize(0.05);
946  if (pfpAssociation) { clID.SetTextColor(color); }
947  else {
948  clID.SetTextColor(kBlack);
949  }
950  } // recoOpt->fDrawClusters > 3
951  }
952  else {
953 
954  // default "outline" method:
955  std::vector<double> tpts, wpts;
956 
957  GetClusterOutlines(hits, tpts, wpts, plane);
958 
959  int lcolor = 9; // line color
960  int fcolor = 9; // fill color
961  int width = 2; // line width
962  int style = 1; // 1=solid line style
963  if (view != 0) {
964  TPolyLine& p1 = view->AddPolyLine(wpts.size(), lcolor, width, style);
965  TPolyLine& p2 = view->AddPolyLine(wpts.size(), lcolor, width, style);
966  p1.SetOption("f");
967  p1.SetFillStyle(3003);
968  p1.SetFillColor(fcolor);
969  for (size_t i = 0; i < wpts.size(); ++i) {
970  if (rawOpt->fAxisOrientation < 1) {
971  p1.SetPoint(i, wpts[i], tpts[i]);
972  p2.SetPoint(i, wpts[i], tpts[i]);
973  }
974  else {
975  p1.SetPoint(i, tpts[i], wpts[i]);
976  p2.SetPoint(i, tpts[i], wpts[i]);
977  }
978  } // loop on i points in ZX view
979  } // if we have a cluster in the ZX view
980  } // end if outline mode
981 
982  // draw the direction cosine of the cluster as well as it's starting point
983  // (average of the start and end angle -- by default they are the same value)
984  // thetawire is the angle measured CW from +z axis to wire
985  double wirePitch = planeg.WirePitch();
986  double driftvelocity = detProp.DriftVelocity(); // cm/us
987  double timetick = sampling_rate(clockData) * 1e-3; // time sample in us
988  // rotate coord system CCW around x-axis by pi-thetawire
989  // new yprime direction is perpendicular to the wire direction
990  // in the same plane as the wires and in the direction of
991  // increasing wire number
992  //use yprime-component of dir cos in rotated coord sys to get
993  // dTdW (number of time ticks per unit of wire pitch)
994  Draw2DSlopeEndPoints(clust[ic]->StartWire(),
995  clust[ic]->StartTick(),
996  clust[ic]->EndWire(),
997  clust[ic]->EndTick(),
998  std::tan((clust[ic]->StartAngle() + clust[ic]->EndAngle()) / 2.) *
999  wirePitch / driftvelocity / timetick,
1000  evd::kColor[colorIdx],
1001  view);
1002 
1003  } // loop on ic clusters
1004  } // loop on imod folders
1005  }
1006 
1007  //......................................................................
1009  double yStart,
1010  double xEnd,
1011  double yEnd,
1012  double slope,
1013  int color,
1014  evdb::View2D* view)
1015  {
1018 
1019  if (recoOpt->fDraw2DSlopeEndPoints < 1) return;
1020 
1021  double x1 = xStart;
1022  double y1 = yStart;
1023  double x2 = xEnd;
1024  double slope1 = slope;
1025 
1026  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
1027  if (rawOpt->fAxisOrientation > 0) {
1028  x1 = yStart;
1029  y1 = xStart;
1030  x2 = yEnd;
1031  if (std::abs(slope) > 0.)
1032  slope1 = 1. / slope;
1033  else
1034  slope1 = 1.e6;
1035  }
1036 
1037  double deltaX = 0.5 * (x2 - x1);
1038  double xm = x1 + deltaX;
1039  double ym = y1 + deltaX * slope;
1040 
1041  TMarker& strt = view->AddMarker(xm, ym, color, kFullCircle, 1.0);
1042  strt.SetMarkerColor(color); // stupid line to shut up compiler warning
1043 
1044  double stublen = 2. * deltaX;
1045  TLine& l = view->AddLine(x1, y1, x1 + stublen, y1 + slope1 * stublen);
1046  l.SetLineColor(color);
1047  l.SetLineWidth(1); //2);
1048  }
1049 
1050  //......................................................................
1052  double y,
1053  double slope,
1054  int color,
1055  evdb::View2D* view)
1056  {
1059 
1060  if (recoOpt->fDraw2DSlopeEndPoints < 1) return;
1061 
1062  double x1 = x;
1063  double y1 = y;
1064  double slope1 = slope;
1065 
1066  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
1067  if (rawOpt->fAxisOrientation > 0) {
1068  x1 = y;
1069  y1 = x;
1070  if (std::abs(slope) > 0.)
1071  slope1 = 1. / slope;
1072  else
1073  slope1 = 1.e6;
1074  }
1075 
1076  TMarker& strt = view->AddMarker(x1, y1, color, kFullStar, 2.0);
1077  strt.SetMarkerColor(color); // stupid line to shut up compiler warning
1078 
1079  double stublen = 300.0;
1080  TLine& l = view->AddLine(x1, y1, x1 + stublen, y1 + slope1 * stublen);
1081  l.SetLineColor(color);
1082  l.SetLineWidth(2);
1083  l.SetLineStyle(2);
1084  }
1085 
1086  //......................................................................
1088  double y,
1089  double cosx,
1090  double cosy,
1091  int color,
1092  evdb::View2D* view)
1093  {
1096 
1097  if (recoOpt->fDraw2DSlopeEndPoints < 1) return;
1098 
1099  double x1 = x;
1100  double y1 = y;
1101  double cosx1 = cosx;
1102  double cosy1 = cosy;
1103 
1104  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
1105  if (rawOpt->fAxisOrientation > 0) {
1106  x1 = y;
1107  y1 = x;
1108  cosx1 = cosy;
1109  cosy1 = cosx;
1110  }
1111 
1112  TMarker& strt = view->AddMarker(x1, y1, color, kFullStar, 2.0);
1113  strt.SetMarkerColor(color); // stupid line to shut up compiler warning
1114 
1115  double stublen = 300.0;
1116  TLine& l = view->AddLine(x1, y1, x1 + stublen * cosx1, y1 + stublen * cosy1);
1117  l.SetLineColor(color);
1118  l.SetLineWidth(2);
1119  l.SetLineStyle(2);
1120  }
1121 
1122  //......................................................................
1131  void RecoBaseDrawer::GetClusterOutlines(std::vector<const recob::Hit*>& hits,
1132  std::vector<double>& wpts,
1133  std::vector<double>& tpts,
1134  unsigned int plane)
1135  {
1137 
1138  // Map wire numbers to highest and lowest in the plane
1139  std::map<unsigned int, double> wlo, whi;
1140  // On first pass, initialize
1141  for (size_t j = 0; j < hits.size(); ++j) {
1142  // check that we are on the correct plane and TPC
1143  if (hits[j]->WireID().Plane != plane || hits[j]->WireID().TPC != rawOpt->fTPC ||
1144  hits[j]->WireID().Cryostat != rawOpt->fCryostat)
1145  continue;
1146 
1147  wlo[hits[j]->WireID().Wire] = hits[j]->PeakTime();
1148  whi[hits[j]->WireID().Wire] = hits[j]->PeakTime();
1149  }
1150 
1151  double t = 0.;
1152 
1153  // Finalize on second pass
1154  for (size_t j = 0; j < hits.size(); ++j) {
1155  t = hits[j]->PeakTime();
1156 
1157  if (t < wlo[hits[j]->WireID().Wire]) wlo[hits[j]->WireID().Wire] = t;
1158  if (t > whi[hits[j]->WireID().Wire]) whi[hits[j]->WireID().Wire] = t;
1159  }
1160 
1161  // Loop over wires and low times to make lines along bottom
1162  // edge. Work from upstream edge to downstream edge
1164  std::map<unsigned int, double>::iterator itrEnd(wlo.end());
1165  for (; itr != itrEnd; ++itr) {
1166  unsigned int w = itr->first;
1167  t = itr->second;
1168 
1169  wpts.push_back(1. * w - 0.1);
1170  tpts.push_back(t - 0.1);
1171  wpts.push_back(1. * w + 0.1);
1172  tpts.push_back(t - 0.1);
1173  }
1174 
1175  // Loop over planes and high cells to make lines along top
1176  // edge. Work from downstream edge toward upstream edge
1177  std::map<unsigned int, double>::reverse_iterator ritr(whi.rbegin());
1178  std::map<unsigned int, double>::reverse_iterator ritrEnd(whi.rend());
1179  for (; ritr != ritrEnd; ++ritr) {
1180  unsigned int w = ritr->first;
1181  t = ritr->second;
1182 
1183  wpts.push_back(1. * w + 0.1);
1184  tpts.push_back(t + 0.1);
1185  wpts.push_back(1. * w - 0.1);
1186  tpts.push_back(t + 0.1);
1187  }
1188 
1189  // Add link to starting point to close the box
1190  wpts.push_back(wpts[0]);
1191  tpts.push_back(tpts[0]);
1192 
1193  return;
1194  }
1195 
1196  //......................................................................
1198  std::vector<const recob::Hit*>& hits,
1199  evdb::View2D* view,
1200  unsigned int plane,
1201  TVector3 const& startPos,
1202  TVector3 const& startDir,
1203  int id,
1204  float cscore)
1205  {
1208 
1209  unsigned int c = rawOpt->fCryostat;
1210  unsigned int t = rawOpt->fTPC;
1211  geo::PlaneID const planeID(c, t, plane);
1212  geo::Point_t localPos(startPos.X(), startPos.Y(), startPos.Z());
1213  auto const& planeg = getWireReadoutGeom().Plane(planeID);
1214 
1215  int color(evd::kColor2[id % evd::kNCOLS]);
1216  int lineWidth(1);
1217 
1218  if (cscore > 0.1 && recoOpt->fDrawCosmicTags) {
1219  color = kRed;
1220  if (cscore < 0.6) color = kMagenta;
1221  lineWidth = 3;
1222  }
1223  else if (cscore < -10000) { //shower hits
1224  lineWidth = 3;
1225  }
1226 
1227  // first draw the hits
1228  if (cscore < -1000) { //shower
1229  Hit2D(hits, color, view, false, false, lineWidth);
1230  if (recoOpt->fDrawShowers >= 1) {
1231  //draw the shower ID at the beginning of shower
1232  std::string s = std::to_string(id);
1233  char const* txt = s.c_str();
1234  double tick = 30 + detProp.ConvertXToTicks(startPos.X(), planeID);
1235  double wire = planeg.WireCoordinate(localPos);
1236  TText& shwID = view->AddText(wire, tick, txt);
1237  shwID.SetTextColor(evd::kColor2[id % evd::kNCOLS]);
1238  shwID.SetTextSize(0.1);
1239  }
1240  }
1241  else
1242  Hit2D(hits, color, view, false, false, lineWidth);
1243 
1244  double tick0 = detProp.ConvertXToTicks(startPos.X(), planeID);
1245  double wire0 = planeg.WireCoordinate(localPos);
1246 
1247  localPos = geo::Point_t(startPos + startDir); // Huh? what is this?
1248 
1249  double tick1 = detProp.ConvertXToTicks((startPos + startDir).X(), planeID);
1250  double wire1 = planeg.WireCoordinate(localPos);
1251  double cost = 0;
1252  double cosw = 0;
1253  double ds = sqrt(pow(tick0 - tick1, 2) + pow(wire0 - wire1, 2));
1254 
1255  if (ds) {
1256  cost = (tick1 - tick0) / ds;
1257  cosw = (wire1 - wire0) / ds;
1258  }
1259 
1260  Draw2DSlopeEndPoints(wire0, tick0, cosw, cost, evd::kColor[id % evd::kNCOLS], view);
1261  }
1262 
1263  //......................................................................
1265  detinfo::DetectorPropertiesData const& detProp,
1266  std::vector<const recob::Hit*>& hits,
1267  evdb::View2D* view,
1268  unsigned int plane,
1269  const recob::Track* track,
1270  int color,
1271  int lineWidth)
1272  {
1276  geo::PlaneID const planeID{rawOpt->fCryostat, rawOpt->fTPC, plane};
1277  auto const& planeg = getWireReadoutGeom().Plane(planeID);
1278 
1279  // first draw the hits
1280  Hit2D(hits, color, view, false, true, lineWidth);
1281 
1282  const auto& startPos = track->Vertex();
1283  const auto& startDir = track->VertexDirection();
1284 
1285  // prepare to draw prongs
1286  geo::PlaneGeo::LocalPoint_t const local{};
1287  auto world = planeg.toWorldCoords(local);
1288  world.SetY(startPos.Y());
1289  world.SetZ(startPos.Z());
1290 
1291  // convert the starting position and direction from 3D to 2D coordinates
1292  double tick = detProp.ConvertXToTicks(startPos.X(), planeID);
1293  double wire = 0.;
1294  try {
1295  wire = 1. * planeg.NearestWireID(world).Wire;
1296  }
1297  catch (cet::exception& e) {
1298  wire = 1. * atoi(e.explain_self().substr(e.explain_self().find("#") + 1, 5).c_str());
1299  }
1300 
1301  // thetawire is the angle measured CW from +z axis to wire
1302  double thetawire = planeg.Wire(0).ThetaZ();
1303  double wirePitch = planeg.WirePitch();
1304  double driftvelocity = detProp.DriftVelocity(); // cm/us
1305  double timetick = sampling_rate(clockData) * 1e-3; // time sample in us
1306  // rotate coord system CCW around x-axis by pi-thetawire
1307  // new yprime direction is perpendicular to the wire direction
1308  // in the same plane as the wires and in the direction of
1309  // increasing wire number
1310  //use yprime-component of dir cos in rotated coord sys to get
1311  // dTdW (number of time ticks per unit of wire pitch)
1312  double rotang = 3.1416 - thetawire;
1313  double yprime = std::cos(rotang) * startDir.Y() + std::sin(rotang) * startDir.Z();
1314  double dTdW = startDir.X() * wirePitch / driftvelocity / timetick / yprime;
1315 
1316  Draw2DSlopeEndPoints(wire, tick, dTdW, color, view);
1317 
1318  // Draw a line to the hit positions, starting from the vertex
1319  size_t nTrackHits = track->NumberTrajectoryPoints();
1320  TPolyLine& pl = view->AddPolyLine(0, 1, 1, 0); //kColor[id%evd::kNCOLS],1,0);
1321 
1322  size_t vidx = 0;
1323  for (size_t idx = 0; idx < nTrackHits; idx++) {
1324  if (track->HasValidPoint(idx) == 0) continue;
1325  const auto& hitPos = track->LocationAtPoint(idx);
1326 
1327  // Use "world" from above
1328  world.SetY(hitPos.Y());
1329  world.SetZ(hitPos.Z());
1330 
1331  // convert the starting position and direction from 3D to 2D coordinates
1332  double tickHit = detProp.ConvertXToTicks(hitPos.X(), planeID);
1333  double wireHit = 0.;
1334  try {
1335  wireHit = 1. * planeg.NearestWireID(world).Wire;
1336  }
1337  catch (cet::exception& e) {
1338  wireHit = 1. * atoi(e.explain_self().substr(e.explain_self().find("#") + 1, 5).c_str());
1339  }
1340  geo::TPCID const tpcid = geo->FindTPCAtPosition(hitPos);
1341  if (tpcid.TPC == planeID.TPC && tpcid.Cryostat == planeID.Cryostat) {
1342  pl.SetPoint(vidx++, wireHit, tickHit);
1343  }
1344  }
1345  }
1346 
1347  //......................................................................
1349  detinfo::DetectorClocksData const& clockData,
1350  detinfo::DetectorPropertiesData const& detProp,
1351  evdb::View2D* view,
1352  unsigned int plane)
1353  {
1356 
1357  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
1358 
1359  geo::PlaneID const planeID{rawOpt->fCryostat, rawOpt->fTPC, plane};
1360  auto const& planeg = getWireReadoutGeom().Plane(planeID);
1361  geo::View_t gview = planeg.View();
1362 
1363  // annoying for now, but have to have multiple copies of basically the
1364  // same code to draw prongs, showers and tracks so that we can use
1365  // the art::Assns to get the hits and clusters.
1366 
1367  int tid = 0;
1368 
1369  if (recoOpt->fDrawTracks != 0) {
1370  for (size_t imod = 0; imod < recoOpt->fTrackLabels.size(); ++imod) {
1371  art::InputTag const which = recoOpt->fTrackLabels[imod];
1372 
1374  GetTracks(evt, which, track);
1375 
1376  if (track.vals().size() < 1) continue;
1377 
1378  art::FindMany<recob::Hit> fmh(track, evt, which);
1379 
1380  art::InputTag const whichTag(
1381  recoOpt->fCosmicTagLabels.size() > imod ? recoOpt->fCosmicTagLabels[imod] : "");
1382  art::FindManyP<anab::CosmicTag> cosmicTrackTags(track, evt, whichTag);
1383 
1384  auto tracksProxy = proxy::getCollection<proxy::Tracks>(evt, which);
1385 
1386  // loop over the prongs and get the clusters and hits associated with
1387  // them. only keep those that are in this view
1388  for (size_t t = 0; t < track.vals().size(); ++t) {
1389  // Check for possible issue
1390  if (track.vals().at(t)->NumberTrajectoryPoints() == 0) {
1391  std::cout << "***** Track with no trajectory points ********" << std::endl;
1392  continue;
1393  }
1394 
1395  if (recoOpt->fDrawTracks > 1) {
1396  // BB: draw the track ID at the end of the track
1397  geo::Point_t trackPos(track.vals().at(t)->End().X(),
1398  track.vals().at(t)->End().Y(),
1399  track.vals().at(t)->End().Z());
1400  double tick = 30 + detProp.ConvertXToTicks(trackPos.X(), planeID);
1401  double wire = planeg.WireCoordinate(trackPos);
1402  tid =
1403  track.vals().at(t)->ID() &
1404  65535; //this is a hack for PMA track id which uses the 16th bit to identify shower-like track.;
1405  std::string s = std::to_string(tid);
1406  char const* txt = s.c_str();
1407  TText& trkID = view->AddText(wire, tick, txt);
1408  trkID.SetTextColor(evd::kColor[tid % evd::kNCOLS]);
1409  trkID.SetTextSize(0.1);
1410  }
1411 
1412  float Score = -999;
1413  if (cosmicTrackTags.isValid()) {
1414  if (cosmicTrackTags.at(t).size() > 0) {
1415  art::Ptr<anab::CosmicTag> currentTag = cosmicTrackTags.at(t).at(0);
1416  Score = currentTag->CosmicScore();
1417  }
1418  }
1419 
1420  std::vector<const recob::Hit*> hits;
1421  if (track.vals().at(t)->NumberTrajectoryPoints() == fmh.at(t).size()) {
1422  auto tp = tracksProxy[t];
1423  for (auto point : tp.points()) {
1424  if (!point.isPointValid()) continue;
1425  hits.push_back(point.hit());
1426  }
1427  }
1428  else {
1429  hits = fmh.at(t);
1430  }
1431  // only get the hits for the current view
1432  std::vector<const recob::Hit*>::iterator itr = hits.begin();
1433  while (itr < hits.end()) {
1434  if ((*itr)->View() != gview)
1435  hits.erase(itr);
1436  else
1437  itr++;
1438  }
1439 
1440  const recob::Track* aTrack(track.vals().at(t));
1441  int color(evd::kColor[(aTrack->ID() & 65535) % evd::kNCOLS]);
1442  int lineWidth(1);
1443 
1444  if (Score > 0.1 && recoOpt->fDrawCosmicTags) {
1445  color = kRed;
1446  if (Score < 0.6) color = kMagenta;
1447  lineWidth = 3;
1448  }
1449  else if (Score < -10000) { //shower hits
1450  lineWidth = 3;
1451  }
1452 
1453  DrawTrack2D(clockData, detProp, hits, view, plane, aTrack, color, lineWidth);
1454  } // end loop over prongs
1455  } // end loop over labels
1456  } // end draw tracks
1457 
1458  if (recoOpt->fDrawShowers != 0) {
1459  static bool first = true;
1460 
1461  if (first) {
1462  std::cout << "DrawShower options: \n";
1463  std::cout << " 1 = Hits in shower color-coded by the shower ID\n";
1464  std::cout << " 2 = Same as 1 + shower axis and circle representing the shower cone\n";
1465  std::cout << " Black cone = shower start dE/dx < 1 MeV/cm (< 1/2 MIP)\n";
1466  std::cout << " Blue cone = shower start dE/dx < 3 MeV/cm (~1 MIP)\n";
1467  std::cout << " Green cone = shower start 3 MeV/cm < dE/dx < 5 MeV/cm (~2 MIP)\n";
1468  std::cout << " Red cone = shower start 5 MeV/cm < dE/dx (>2 MIP)\n";
1469  first = false;
1470  }
1471  for (size_t imod = 0; imod < recoOpt->fShowerLabels.size(); ++imod) {
1472  art::InputTag const which = recoOpt->fShowerLabels[imod];
1473 
1475  GetShowers(evt, which, shower);
1476  if (shower.vals().size() < 1) continue;
1477 
1478  art::FindMany<recob::Hit> fmh(shower, evt, which);
1479 
1480  // loop over the prongs and get the clusters and hits associated with
1481  // them. only keep those that are in this view
1482  for (size_t s = 0; s < shower.vals().size(); ++s) {
1483 
1484  std::vector<const recob::Hit*> hits = fmh.at(s);
1485  // only get the hits for the current view
1486  std::vector<const recob::Hit*>::iterator itr = hits.begin();
1487  while (itr < hits.end()) {
1488  if ((*itr)->View() != gview)
1489  hits.erase(itr);
1490  else
1491  itr++;
1492  }
1493  if (recoOpt->fDrawShowers > 1) {
1494  // BB draw a line between the start and end points and a "circle" that represents
1495  // the shower cone angle at the end point
1496  if (!shower.vals().at(s)->has_length()) continue;
1497  if (!shower.vals().at(s)->has_open_angle()) continue;
1498 
1499  TVector3 startPos = shower.vals().at(s)->ShowerStart();
1500  TVector3 dir = shower.vals().at(s)->Direction();
1501  double length = shower.vals().at(s)->Length();
1502  double openAngle = shower.vals().at(s)->OpenAngle();
1503 
1504  // Find the center of the cone base
1505  TVector3 endPos = startPos + length * dir;
1506 
1507  geo::Point_t localStart(startPos);
1508  geo::Point_t localEnd(endPos);
1509 
1510  double swire = planeg.WireCoordinate(localStart);
1511  double stick = detProp.ConvertXToTicks(startPos.X(), planeID);
1512  double ewire = planeg.WireCoordinate(localEnd);
1513  double etick = detProp.ConvertXToTicks(endPos.X(), planeID);
1514  TLine& coneLine = view->AddLine(swire, stick, ewire, etick);
1515  // color coding by dE/dx
1516  std::vector<double> dedxVec = shower.vals().at(s)->dEdx();
1517  // use black for too-low dE/dx
1518  int color = kBlack;
1519  if (plane < dedxVec.size()) {
1520  if (dedxVec[plane] > 1 && dedxVec[plane] < 3) {
1521  // use blue for ~1 MIP
1522  color = kBlue;
1523  }
1524  else if (dedxVec[plane] < 5) {
1525  // use green for ~2 MIP
1526  color = kGreen;
1527  }
1528  else {
1529  // use red for >~ 2 MIP
1530  color = kRed;
1531  }
1532  }
1533  coneLine.SetLineColor(color);
1534 
1535  // Now find the 3D circle that represents the base of the cone
1536  double radius = length * openAngle;
1537  auto coneRim = Circle3D(endPos, dir, radius);
1538  TPolyLine& pline = view->AddPolyLine(coneRim.size(), color, 2, 0);
1539  // project these points into the plane
1540  for (unsigned short ipt = 0; ipt < coneRim.size(); ++ipt) {
1541  geo::Point_t localPos(coneRim[ipt][0], coneRim[ipt][1], coneRim[ipt][2]);
1542  double wire = planeg.WireCoordinate(localPos);
1543  double tick = detProp.ConvertXToTicks(coneRim[ipt][0], planeID);
1544  pline.SetPoint(ipt, wire, tick);
1545  } // ipt
1546  }
1547  DrawProng2D(detProp,
1548  hits,
1549  view,
1550  plane,
1551  shower.vals().at(s)->ShowerStart(),
1552  shower.vals().at(s)->Direction(),
1553  s,
1554  -10001); //use -10001 to increase shower hit size
1555 
1556  } // end loop over prongs
1557  } // end loop over labels
1558  } // end draw showers
1559  }
1560 
1561  //......................................................................
1563  detinfo::DetectorClocksData const& clockData,
1564  detinfo::DetectorPropertiesData const& detProp,
1565  evdb::View2D* view,
1566  unsigned int plane)
1567  {
1569  if (!recoOpt->fDrawTrackVertexAssns) return;
1570 
1572 
1573  geo::PlaneID const planeID{rawOpt->fCryostat, rawOpt->fTPC, plane};
1574  auto const& planeg = getWireReadoutGeom().Plane(planeID);
1575  geo::View_t gview = planeg.View();
1576 
1577  // annoying for now, but have to have multiple copies of basically the
1578  // same code to draw prongs, showers and tracks so that we can use
1579  // the art::Assns to get the hits and clusters.
1580 
1581  int tid = 0;
1582 
1583  for (size_t imod = 0; imod < recoOpt->fTrkVtxTrackLabels.size(); ++imod) {
1584  art::InputTag const which = recoOpt->fTrkVtxTrackLabels[imod];
1585 
1586  art::View<recob::Track> trackCol;
1587  GetTracks(evt, which, trackCol);
1588 
1589  if (trackCol.vals().size() < 1) continue;
1590 
1591  // Recover associations output from the filter
1592  std::unique_ptr<art::Assns<recob::Vertex, recob::Track>> vertexTrackAssociations(
1594 
1595  // Recover a handle to the collection of associations between vertices and tracks
1596  // This is a bit non-standard way to do this but trying to avoid complications
1598 
1599  evt.getByLabel(recoOpt->fTrkVtxFilterLabels[imod], vertexTrackAssnsHandle);
1600 
1601  if (vertexTrackAssnsHandle->size() < 1) continue;
1602 
1603  // Get the rest of the associations in the standard way
1604  art::FindMany<recob::Hit> fmh(trackCol, evt, which);
1605 
1606  art::FindManyP<anab::CosmicTag> cosmicTrackTags(
1607  trackCol, evt, recoOpt->fTrkVtxCosmicLabels[imod]);
1608 
1609  auto tracksProxy = proxy::getCollection<proxy::Tracks>(evt, which);
1610 
1611  // Need to keep track of vertices unfortunately
1612  int lastVtxIdx(-1);
1613  int color(kRed);
1614 
1615  std::cout << "==> Neutrino Candidate drawing for tagger "
1616  << recoOpt->fTrkVtxFilterLabels[imod] << std::endl;
1617 
1618  // Now we can iterate over the vertex/track associations and do some drawing
1619  for (const auto& vertexTrackAssn : *vertexTrackAssnsHandle) {
1620  // Start by drawing the vertex
1621  art::Ptr<recob::Vertex> vertex = vertexTrackAssn.first;
1622 
1623  if (vertex->ID() != lastVtxIdx) {
1624  // BB: draw polymarker at the vertex position in this plane
1625  double xyz[3];
1626 
1627  vertex->XYZ(xyz);
1628 
1629  geo::Point_t localXYZ(xyz[0], xyz[1], xyz[2]);
1630 
1631  double wire = planeg.WireCoordinate(localXYZ);
1632  double time = detProp.ConvertXToTicks(xyz[0], planeID);
1633 
1634  TMarker& strt = view->AddMarker(wire, time, color, 24, 3.0);
1635  strt.SetMarkerColor(color);
1636 
1637  std::cout << " --> Drawing vertex id: " << vertex->ID() << std::endl;
1638  }
1639 
1640  lastVtxIdx = vertex->ID();
1641 
1642  const art::Ptr<recob::Track>& track = vertexTrackAssn.second;
1643 
1644  // BB: draw the track ID at the end of the track
1645  double x = track->End().X();
1646  geo::Point_t trackEnd(track->End());
1647  double tick = 30 + detProp.ConvertXToTicks(x, planeID);
1648  double wire = planeg.WireCoordinate(trackEnd);
1649 
1650  tid = track->ID() & 65535;
1651 
1652  std::cout << " --> Drawing Track id: " << tid << std::endl;
1653 
1654  std::string s = std::to_string(tid);
1655  char const* txt = s.c_str();
1656 
1657  TText& trkID = view->AddText(wire, tick, txt);
1658  trkID.SetTextColor(color);
1659  trkID.SetTextSize(0.1);
1660 
1661  float cosmicScore = -999;
1662  if (cosmicTrackTags.isValid()) {
1663  if (cosmicTrackTags.at(track.key()).size() > 0) {
1664  art::Ptr<anab::CosmicTag> currentTag = cosmicTrackTags.at(track.key()).at(0);
1665  cosmicScore = currentTag->CosmicScore();
1666  }
1667  }
1668 
1669  std::vector<const recob::Hit*> hits;
1670  if (track->NumberTrajectoryPoints() == fmh.at(track.key()).size()) {
1671  auto tp = tracksProxy[track.key()];
1672  for (auto point : tp.points()) {
1673  if (!point.isPointValid()) continue;
1674  hits.push_back(point.hit());
1675  }
1676  }
1677  else {
1678  hits = fmh.at(track.key());
1679  }
1680  // only get the hits for the current view
1681  std::vector<const recob::Hit*>::iterator itr = hits.begin();
1682  while (itr < hits.end()) {
1683  if ((*itr)->View() != gview)
1684  hits.erase(itr);
1685  else
1686  itr++;
1687  }
1688 
1689  int lineWidth(1);
1690 
1691  if (cosmicScore > 0.1) {
1692  color = kRed;
1693  if (cosmicScore < 0.6) color = kMagenta;
1694  lineWidth = 3;
1695  }
1696  else if (cosmicScore < -10000) { //shower hits
1697  lineWidth = 3;
1698  }
1699 
1700  DrawTrack2D(clockData, detProp, hits, view, plane, track.get(), color, lineWidth);
1701 
1702  } // end loop over vertex/track associations
1703 
1704  } // end loop over labels
1705  }
1706 
1707  //......................................................................
1709  detinfo::DetectorPropertiesData const& detProp,
1710  evdb::View2D* view,
1711  unsigned int plane)
1712  {
1715 
1716  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
1717  if (recoOpt->fDrawVertices == 0) return;
1718 
1720  static bool first = true;
1721 
1722  if (first) {
1723  std::cout << "******** DrawVertices: Open circles color coded across all planes. Set "
1724  "DrawVertices > 1 to display the vertex ID\n";
1725  first = false;
1726  }
1727 
1728  geo::PlaneID const planeID{rawOpt->fCryostat, rawOpt->fTPC, plane};
1729  auto const& planeg = getWireReadoutGeom().Plane(planeID);
1730 
1731  for (size_t imod = 0; imod < recoOpt->fVertexLabels.size(); ++imod) {
1732  art::InputTag const which = recoOpt->fVertexLabels[imod];
1733 
1735  GetVertices(evt, which, vertex);
1736 
1737  if (vertex.size() < 1) continue;
1738 
1739  const geo::TPCGeo& tpc = geo->TPC(planeID);
1740  auto const world = tpc.GetCenter();
1741  double minxyz[3], maxxyz[3];
1742  minxyz[0] = world.X() - tpc.HalfWidth();
1743  maxxyz[0] = world.X() + tpc.HalfWidth();
1744  minxyz[1] = world.Y() - tpc.HalfWidth();
1745  maxxyz[1] = world.Y() + tpc.HalfWidth();
1746  minxyz[2] = world.Z() - tpc.Length() / 2;
1747  maxxyz[2] = world.Z() + tpc.Length() / 2;
1748 
1749  for (size_t v = 0; v < vertex.size(); ++v) {
1750  // ensure the vertex is inside the current tpc
1751  double xyz[3];
1752  vertex[v]->XYZ(xyz);
1753  if (xyz[0] < minxyz[0] || xyz[0] > maxxyz[0]) continue;
1754  if (xyz[1] < minxyz[1] || xyz[1] > maxxyz[1]) continue;
1755  if (xyz[2] < minxyz[2] || xyz[2] > maxxyz[2]) continue;
1756 
1757  geo::Point_t localPos(xyz[0], xyz[1], xyz[2]);
1758 
1759  // BB: draw polymarker at the vertex position in this plane
1760  double wire = planeg.WireCoordinate(localPos);
1761  double time = detProp.ConvertXToTicks(xyz[0], planeID);
1762  int color = evd::kColor[vertex[v]->ID() % evd::kNCOLS];
1763  TMarker& strt = view->AddMarker(wire, time, color, 24, 1.0);
1764  strt.SetMarkerColor(color);
1765 
1766  // BB: draw the vertex ID
1767  if (recoOpt->fDrawVertices > 1) {
1768  std::string s = "3V" + std::to_string(vertex[v]->ID());
1769  char const* txt = s.c_str();
1770  TText& vtxID = view->AddText(wire, time + 30, txt);
1771  vtxID.SetTextColor(color);
1772  vtxID.SetTextSize(0.05);
1773  }
1774  } // end loop over vertices to draw from this label
1775  } // end loop over vertex module lables
1776  }
1777 
1778  //......................................................................
1779  void RecoBaseDrawer::Event2D(const art::Event& evt, evdb::View2D* view, unsigned int plane)
1780  {
1783  auto const& wireReadoutGeom = getWireReadoutGeom();
1784 
1785  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
1786 
1787  if (recoOpt->fDrawEvents != 0) {
1788  geo::PlaneID const planeID{rawOpt->fCryostat, rawOpt->fTPC, plane};
1789  geo::View_t gview = wireReadoutGeom.Plane(planeID).View();
1790 
1791  for (unsigned int imod = 0; imod < recoOpt->fEventLabels.size(); ++imod) {
1792  art::InputTag const which = recoOpt->fEventLabels[imod];
1793 
1795  GetEvents(evt, which, event);
1796 
1797  if (event.size() < 1) continue;
1798 
1799  art::FindMany<recob::Hit> fmh(event, evt, which);
1800 
1801  for (size_t e = 0; e < event.size(); ++e) {
1802  std::vector<const recob::Hit*> hits;
1803 
1804  hits = fmh.at(e);
1805 
1806  // only get the hits for the current view
1807  std::vector<const recob::Hit*>::iterator itr = hits.begin();
1808  while (itr < hits.end()) {
1809  if ((*itr)->View() != gview)
1810  hits.erase(itr);
1811  else
1812  itr++;
1813  }
1814 
1815  Hit2D(hits, evd::kColor[event[e]->ID() % evd::kNCOLS], view, false, true);
1816  } // end loop over events
1817  } // end loop over event module lables
1818  } // end if we are drawing events
1819 
1820  return;
1821  }
1822 
1823  //......................................................................
1825  {
1828 
1829  std::vector<art::InputTag> labels;
1830  if (recoOpt->fDrawSeeds != 0)
1831  for (size_t imod = 0; imod < recoOpt->fSeedLabels.size(); ++imod)
1832  labels.push_back(recoOpt->fSeedLabels[imod]);
1833 
1834  for (size_t imod = 0; imod < labels.size(); ++imod) {
1835  art::InputTag const which = labels[imod];
1836 
1838  GetSeeds(evt, which, seeds);
1839 
1840  int color = 0;
1841 
1842  if (seeds.size() < 1) continue;
1843 
1844  TPolyMarker3D& pmrk = view->AddPolyMarker3D(seeds.size(), color, 4, 1);
1845 
1846  for (size_t iseed = 0; iseed != seeds.size(); ++iseed) {
1847  double pt[3], pterr[3], dir[3], direrr[3];
1848  seeds.at(iseed)->GetPoint(pt, pterr);
1849  seeds.at(iseed)->GetDirection(dir, direrr);
1850 
1851  double end1[3], end2[3];
1852  for (int i = 0; i != 3; ++i) {
1853  end1[i] = pt[i] + dir[i];
1854  end2[i] = pt[i] - dir[i];
1855  }
1856 
1857  TPolyLine3D& pline = view->AddPolyLine3D(2, color, 2, 0);
1858 
1859  pmrk.SetPoint(iseed, pt[0], pt[1], pt[2]);
1860  pline.SetPoint(0, end1[0], end1[1], end1[2]);
1861  pline.SetPoint(1, end2[0], end2[1], end2[2]);
1862  } // end loop over seeds
1863  } // end loop over module labels
1864 
1865  return;
1866  }
1867 
1868  //......................................................................
1870  {
1873 
1874  std::vector<art::InputTag> labels;
1875  if (recoOpt->fDrawSeeds != 0)
1876  for (size_t imod = 0; imod < recoOpt->fSeedLabels.size(); ++imod)
1877  labels.push_back(recoOpt->fSeedLabels[imod]);
1878 
1879  for (size_t imod = 0; imod < labels.size(); ++imod) {
1880  art::InputTag const which = labels[imod];
1881 
1883  GetSeeds(evt, which, seeds);
1884 
1885  int color = 0;
1886 
1887  for (size_t iseed = 0; iseed != seeds.size(); ++iseed) {
1888  double pt[3], pterr[3], dir[3], direrr[3];
1889  seeds.at(iseed)->GetPoint(pt, pterr);
1890  seeds.at(iseed)->GetDirection(dir, direrr);
1891 
1892  double end1[3], end2[3];
1893  for (int i = 0; i != 3; ++i) {
1894  end1[i] = pt[i] + dir[i];
1895  end2[i] = pt[i] - dir[i];
1896  }
1897 
1898  if (proj == evd::kXY) {
1899  TMarker& strt = view->AddMarker(pt[1], pt[0], color, 4, 1.5);
1900  TLine& line = view->AddLine(end1[1], end1[0], end2[1], end2[0]);
1901  strt.SetMarkerColor(evd::kColor[color]);
1902  line.SetLineColor(evd::kColor[color]);
1903  line.SetLineWidth(2.0);
1904  }
1905  else if (proj == evd::kXZ) {
1906  TMarker& strt = view->AddMarker(pt[2], pt[0], color, 4, 1.5);
1907  TLine& line = view->AddLine(end1[2], end1[0], end2[2], end2[0]);
1908  strt.SetMarkerColor(evd::kColor[color]);
1909  line.SetLineColor(evd::kColor[color]);
1910  line.SetLineWidth(2.0);
1911  }
1912  else {
1913  if (proj != evd::kYZ)
1914  throw cet::exception("RecoBaseDrawer:SeedOrtho")
1915  << "projection is not YZ as expected\n";
1916 
1917  TMarker& strt = view->AddMarker(pt[2], pt[1], color, 4, 1.5);
1918  TLine& line = view->AddLine(end1[2], end1[1], end2[2], end2[1]);
1919  strt.SetMarkerColor(evd::kColor[color]);
1920  line.SetLineColor(evd::kColor[color]);
1921  line.SetLineWidth(2.0);
1922  }
1923  }
1924  }
1925  }
1926 
1927  //......................................................................
1929  {
1932 
1933  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
1934 
1935  std::vector<art::InputTag> labels;
1936  if (recoOpt->fDrawSpacePoints != 0) {
1937  for (size_t imod = 0; imod < recoOpt->fSpacePointLabels.size(); ++imod)
1938  labels.push_back(recoOpt->fSpacePointLabels[imod]);
1939  }
1940 
1941  for (size_t imod = 0; imod < labels.size(); ++imod) {
1942  art::InputTag const which = labels[imod];
1943 
1944  std::vector<art::Ptr<recob::SpacePoint>> spts;
1945  GetSpacePoints(evt, which, spts);
1946  int color = 10 * imod + 11;
1947 
1948  color = 0;
1949 
1950  // std::vector<const recob::SpacePoint*> sptsVec;
1951  //
1952  // sptsVec.resize(spts.size());
1953  // for(const auto& spt : spts){
1954  // std::cout<<spt<<" "<<*spt<<" "<<&*spt<<std::endl;
1955  // sptsVec.push_back(&*spt);
1956  // std::cout<<sptsVec.back()<<std::endl;
1957  // }
1958  fAllSpacePointDrawer->Draw(spts, view, color, kFullDotMedium, 1);
1959  }
1960 
1961  return;
1962  }
1963 
1964  //......................................................................
1966  {
1969 
1970  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
1971  if (recoOpt->fDrawPFParticles < 1) return;
1972 
1973  // The plan is to loop over the list of possible particles
1974  for (size_t imod = 0; imod < recoOpt->fPFParticleLabels.size(); ++imod) {
1975  art::InputTag const which = recoOpt->fPFParticleLabels[imod];
1976  art::InputTag const assns = recoOpt->fSpacePointLabels[imod];
1977 
1978  // Start off by recovering our 3D Clusters for this label
1979  art::PtrVector<recob::PFParticle> pfParticleVec;
1980  GetPFParticles(evt, which, pfParticleVec);
1981 
1982  mf::LogDebug("RecoBaseDrawer")
1983  << "RecoBaseDrawer: number PFParticles to draw: " << pfParticleVec.size() << std::endl;
1984 
1985  // Make sure we have some clusters
1986  if (pfParticleVec.size() < 1) continue;
1987 
1988  // Get the space points created by the PFParticle producer
1989  std::vector<art::Ptr<recob::SpacePoint>> spacePointVec;
1990  GetSpacePoints(evt, assns, spacePointVec);
1991 
1992  // Recover the edges
1993  std::vector<art::Ptr<recob::Edge>> edgeVec;
1994  if (recoOpt->fDrawEdges) GetEdges(evt, assns, edgeVec);
1995 
1996  // No space points no continue
1997  if (spacePointVec.empty()) continue;
1998 
1999  // Add the relations to recover associations cluster hits
2000  art::FindManyP<recob::SpacePoint> edgeSpacePointAssnsVec(edgeVec, evt, assns);
2001  art::FindManyP<recob::SpacePoint> spacePointAssnVec(pfParticleVec, evt, assns);
2002  art::FindManyP<recob::Hit> spHitAssnVec(spacePointVec, evt, assns);
2003  art::FindManyP<recob::Edge> edgeAssnsVec(pfParticleVec, evt, assns);
2004 
2005  // If no valid space point associations then nothing to do
2006  if (!spacePointAssnVec.isValid()) continue;
2007 
2008  // Need the PCA info as well
2009  art::FindMany<recob::PCAxis> pcAxisAssnVec(pfParticleVec, evt, which);
2010 
2011  // Want CR tagging info
2012  // Note the cosmic tags come from a different producer - we assume that the producers are
2013  // matched in the fcl label vectors!
2014  art::InputTag cosmicTagLabel =
2015  imod < recoOpt->fCosmicTagLabels.size() ? recoOpt->fCosmicTagLabels[imod] : "";
2016  art::FindMany<anab::CosmicTag> pfCosmicAssns(pfParticleVec, evt, cosmicTagLabel);
2017 
2018  // We also want to drive display of tracks but have the same issue with production... so follow the
2019  // same prescription.
2020  art::InputTag trackTagLabel =
2021  imod < recoOpt->fTrackLabels.size() ? recoOpt->fTrackLabels[imod] : "";
2022  art::FindMany<recob::Track> pfTrackAssns(pfParticleVec, evt, trackTagLabel);
2023 
2024  // Commence looping over possible clusters
2025  for (size_t idx = 0; idx < pfParticleVec.size(); idx++) {
2026  // Recover cluster
2027  const art::Ptr<recob::PFParticle> pfParticle(pfParticleVec.at(idx));
2028 
2029  // Drawing will be done recursively down the chain of hieirarchy... so we want to begin
2030  // with only "primary" particles, if we find one that isn't then we skip
2031  if (!pfParticle->IsPrimary()) continue;
2032 
2033  // Call the recursive drawing routine
2034  DrawPFParticle3D(pfParticle,
2035  pfParticleVec,
2036  spacePointVec,
2037  edgeAssnsVec,
2038  spacePointAssnVec,
2039  edgeSpacePointAssnsVec,
2040  spHitAssnVec,
2041  pfTrackAssns,
2042  pcAxisAssnVec,
2043  pfCosmicAssns,
2044  0,
2045  view);
2046  }
2047  }
2048 
2049  return;
2050  }
2051 
2053  {
2054  float hitChiSq(0.);
2055 
2056  bool usePlane[] = {false, false, false};
2057  float peakTimeVec[] = {0., 0., 0.};
2058  float peakSigmaVec[] = {0., 0., 0.};
2059  float aveSum(0.);
2060  float weightSum(0.);
2061 
2062  // Temp ad hoc correction to investigate...
2063  std::map<size_t, double> planeOffsetMap;
2064 
2065  planeOffsetMap[0] = 0.;
2066  planeOffsetMap[1] = 4.;
2067  planeOffsetMap[2] = 8.;
2068 
2069  for (const auto& hit : hitVec) {
2070  if (!hit) continue;
2071 
2072  float peakTime = hit->PeakTime() - planeOffsetMap[hit->WireID().Plane];
2073  float peakRMS = hit->RMS();
2074 
2075  aveSum += peakTime / (peakRMS * peakRMS);
2076  weightSum += 1. / (peakRMS * peakRMS);
2077 
2078  peakTimeVec[hit->WireID().Plane] = peakTime;
2079  peakSigmaVec[hit->WireID().Plane] = peakRMS;
2080  usePlane[hit->WireID().Plane] = true;
2081  }
2082 
2083  aveSum /= weightSum;
2084 
2085  for (int idx = 0; idx < 3; idx++) {
2086  if (usePlane[idx]) {
2087  float deltaTime = peakTimeVec[idx] - aveSum;
2088  float sigmaPeakTimeSq = peakSigmaVec[idx] * peakSigmaVec[idx];
2089 
2090  hitChiSq += deltaTime * deltaTime / sigmaPeakTimeSq;
2091  }
2092  }
2093 
2094  return hitChiSq;
2095  }
2096 
2098  const art::Ptr<recob::PFParticle>& pfPart,
2099  const art::PtrVector<recob::PFParticle>& pfParticleVec,
2100  const std::vector<art::Ptr<recob::SpacePoint>>& spacePointVec,
2101  const art::FindManyP<recob::Edge>& edgeAssnsVec,
2102  const art::FindManyP<recob::SpacePoint>& spacePointAssnVec,
2103  const art::FindManyP<recob::SpacePoint>& edgeSPAssnVec,
2104  const art::FindManyP<recob::Hit>& spHitAssnVec,
2105  const art::FindMany<recob::Track>& trackAssnVec,
2106  const art::FindMany<recob::PCAxis>& pcAxisAssnVec,
2107  const art::FindMany<anab::CosmicTag>& cosmicTagAssnVec,
2108  int depth,
2109  evdb::View3D* view)
2110  {
2113 
2114  // First let's draw the hits associated to this cluster
2115  const std::vector<art::Ptr<recob::SpacePoint>>& hitsVec(spacePointAssnVec.at(pfPart.key()));
2116 
2117  // Use the particle ID to determine the color to draw the points
2118  // Ok, this is what we would like to do eventually but currently all particles are the same...
2119  bool isCosmic(false);
2120  int colorIdx(evd::kColor[pfPart->Self() % evd::kNCOLS]);
2121 
2122  // Recover cosmic tag info if any
2123  if (cosmicTagAssnVec.isValid() && recoOpt->fDrawPFParticles > 3) {
2124  std::vector<const anab::CosmicTag*> pfCosmicTagVec = cosmicTagAssnVec.at(pfPart.key());
2125 
2126  if (!pfCosmicTagVec.empty()) {
2127  const anab::CosmicTag* cosmicTag = pfCosmicTagVec.front();
2128 
2129  if (cosmicTag->CosmicScore() > 0.6) isCosmic = true;
2130  }
2131  }
2132 
2133  // Reset color index if a cosmic
2134  if (isCosmic) colorIdx = 12;
2135 
2136  if (!hitsVec.empty() && recoOpt->fDraw3DSpacePoints)
2137  fSpacePointDrawer->Draw(hitsVec, view, 1, kFullDotLarge, 0.25, &spHitAssnVec);
2138  /*
2139  {
2140  using HitPosition = std::array<double,6>;
2141  std::map<int,std::vector<HitPosition>> colorToHitMap;
2142 
2143  float minHitChiSquare(0.);
2144  float maxHitChiSquare(2.);
2145  float hitChiSqScale((cst->fRecoQHigh[geo::kCollection] - cst->fRecoQLow[geo::kCollection]) / (maxHitChiSquare - minHitChiSquare));
2146 
2147  for(const auto& spacePoint : hitsVec)
2148  {
2149  const double* pos = spacePoint->XYZ();
2150  const double* err = spacePoint->ErrXYZ();
2151 
2152  bool storeHit(false);
2153  int chargeColorIdx(0);
2154  float spacePointChiSq(spacePoint->Chisq());
2155 
2156  if (recoOpt->fDraw3DSpacePointHeatMap)
2157  {
2158  storeHit = true;
2159 
2160  float hitChiSq = std::max(minHitChiSquare, std::min(maxHitChiSquare, spacePointChiSq));
2161 
2162  float chgFactor = cst->fRecoQHigh[geo::kCollection] - hitChiSqScale * hitChiSq;
2163  //float chgFactor = delTScaleFctr * hitChiSq + cst->fRecoQLow[geo::kCollection];
2164 
2165  chargeColorIdx = cst->CalQ(geo::kCollection).GetColor(chgFactor);
2166  }
2167  else
2168  {
2169  if (spacePointChiSq > 0. && !recoOpt->fSkeletonOnly) // All cluster hits which are unmarked
2170  {
2171  storeHit = true;
2172  }
2173  else if (spacePointChiSq > -2.) // Skeleton hits
2174  {
2175  chargeColorIdx = 5;
2176  storeHit = true;
2177  }
2178  else if (spacePointChiSq > -3.) // Pure edge hits
2179  {
2180  if (chargeColorIdx < 0) chargeColorIdx = !isCosmic ? 3 : colorIdx + 3;
2181  storeHit = true;
2182  }
2183  else if (spacePointChiSq > -4.) // Skeleton hits which are also edge hits
2184  {
2185  if (chargeColorIdx < 0) chargeColorIdx = !isCosmic ? 0 : colorIdx + 3;
2186  storeHit = true;
2187  }
2188  else if (spacePoint->Chisq() > -5.) // Hits which form seeds for tracks
2189  {
2190  if (chargeColorIdx < 0) chargeColorIdx = !isCosmic ? 5 : colorIdx + 3;
2191  storeHit = true;
2192  }
2193  else if (!recoOpt->fSkeletonOnly) // hits made from pairs
2194  {
2195  chargeColorIdx = 15;
2196  storeHit = true;
2197  }
2198 
2199  if (chargeColorIdx < 0) chargeColorIdx = 0;
2200  }
2201 
2202  if (storeHit) colorToHitMap[chargeColorIdx].push_back(HitPosition()={{pos[0],pos[1],pos[2],err[3],err[3],err[5]}});
2203  }
2204 
2205  size_t nHitsDrawn(0);
2206 
2207  for(auto& hitPair : colorToHitMap)
2208  {
2209  //TPolyMarker3D& pm = view->AddPolyMarker3D(hitPair.second.size(), hitPair.first, kFullDotMedium, 3);
2210  TPolyMarker3D& pm = view->AddPolyMarker3D(hitPair.second.size(), hitPair.first, kFullDotLarge, 0.25); //kFullDotLarge, 0.3);
2211  for (const auto& hit : hitPair.second) pm.SetNextPoint(hit[0],hit[1],hit[2]);
2212 
2213  nHitsDrawn += hitPair.second.size();
2214  }
2215  }
2216 */
2217 
2218  // Now try to draw any associated edges
2219  if (edgeAssnsVec.isValid() && recoOpt->fDraw3DEdges) {
2220  const std::vector<art::Ptr<recob::Edge>>& edgeVec(edgeAssnsVec.at(pfPart.key()));
2221 
2222  if (!edgeVec.empty()) {
2223  TPolyMarker3D& pm = view->AddPolyMarker3D(
2224  2 * edgeVec.size(), colorIdx, kFullDotMedium, 1.25); //kFullDotLarge, 0.5);
2225 
2226  for (const auto& edge : edgeVec) {
2227  try {
2228  const std::vector<art::Ptr<recob::SpacePoint>>& spacePointVec(
2229  edgeSPAssnVec.at(edge.key()));
2230 
2231  if (spacePointVec.size() != 2) {
2232  std::cout << "Space Point vector associated to edge is not of size 2: "
2233  << spacePointVec.size() << std::endl;
2234  continue;
2235  }
2236 
2237  const recob::SpacePoint* firstSP = spacePointVec[0].get();
2238  const recob::SpacePoint* secondSP = spacePointVec[1].get();
2239 
2240  TVector3 startPoint(firstSP->XYZ()[0], firstSP->XYZ()[1], firstSP->XYZ()[2]);
2241  TVector3 endPoint(secondSP->XYZ()[0], secondSP->XYZ()[1], secondSP->XYZ()[2]);
2242  TVector3 lineVec(endPoint - startPoint);
2243 
2244  pm.SetNextPoint(startPoint[0], startPoint[1], startPoint[2]);
2245  pm.SetNextPoint(endPoint[0], endPoint[1], endPoint[2]);
2246 
2247  double length = lineVec.Mag();
2248 
2249  if (length == 0.) {
2250  std::cout << "Edge length is zero, index 1: " << edge->FirstPointID()
2251  << ", index 2: " << edge->SecondPointID() << std::endl;
2252  continue;
2253  }
2254 
2255  double minLen = std::max(2.01, length);
2256 
2257  if (minLen > length) {
2258  lineVec.SetMag(1.);
2259 
2260  startPoint += -0.5 * (minLen - length) * lineVec;
2261  endPoint += 0.5 * (minLen - length) * lineVec;
2262  }
2263 
2264  // Get a polyline object to draw from the first to the second space point
2265  TPolyLine3D& pl = view->AddPolyLine3D(2, colorIdx, 4, 1);
2266 
2267  pl.SetPoint(0, startPoint[0], startPoint[1], startPoint[2]);
2268  pl.SetPoint(1, endPoint[0], endPoint[1], endPoint[2]);
2269  }
2270  catch (...) {
2271  continue;
2272  }
2273  }
2274  }
2275  }
2276 
2277  // Draw associated tracks
2278  if (trackAssnVec.isValid()) {
2279  std::vector<const recob::Track*> trackVec(trackAssnVec.at(pfPart.key()));
2280 
2281  if (!trackVec.empty()) {
2282  for (const auto& track : trackVec)
2283  DrawTrack3D(*track, view, colorIdx, kFullDotLarge, 0.5);
2284  }
2285  }
2286 
2287  // Look up the PCA info
2288  if (pcAxisAssnVec.isValid() && recoOpt->fDraw3DPCAAxes) {
2289  std::vector<const recob::PCAxis*> pcaVec(pcAxisAssnVec.at(pfPart.key()));
2290 
2291  if (!pcaVec.empty()) {
2292  // For each axis we are going to draw a solid line between two points
2293  int numPoints(2);
2294  //int lineWidth[2] = { 3, 1};
2295  int lineWidth[2] = {2, 1};
2296  int lineStyle[2] = {1, 13};
2297  int lineColor[2] = {colorIdx, 18};
2298  //int markStyle[2] = { 4, 4};
2299  int markStyle[2] = {kFullDotLarge, kFullDotLarge};
2300  double markSize[2] = {0.5, 0.2};
2301  int pcaIdx(0);
2302 
2303  if (!isCosmic) lineColor[1] = colorIdx;
2304 
2305  // The order of axes in the returned association vector is arbitrary... the "first" axis is
2306  // better and we can divine that by looking at the axis id's (the best will have been made first)
2307  if (pcaVec.size() > 1 && pcaVec.front()->getID() > pcaVec.back()->getID())
2308  std::reverse(pcaVec.begin(), pcaVec.end());
2309 
2310  for (const auto& pca : pcaVec) {
2311  // We need the mean position
2312  const double* avePosition = pca->getAvePosition();
2313 
2314  // Let's draw a marker at the interesting points
2315  int pmrkIdx(0);
2316  TPolyMarker3D& pmrk =
2317  view->AddPolyMarker3D(7, lineColor[pcaIdx], markStyle[pcaIdx], markSize[pcaIdx]);
2318 
2319  pmrk.SetPoint(pmrkIdx++, avePosition[0], avePosition[1], avePosition[2]);
2320 
2321  // Loop over pca dimensions
2322  for (int dimIdx = 0; dimIdx < 3; dimIdx++) {
2323  // Oh please oh please give me an instance of a poly line...
2324  TPolyLine3D& pl = view->AddPolyLine3D(
2325  numPoints, lineColor[pcaIdx], lineWidth[pcaIdx], lineStyle[pcaIdx]);
2326 
2327  // We will use the eigen value to give the length of the line we're going to plot
2328  double eigenValue = pca->getEigenValues()[dimIdx];
2329 
2330  // Make sure a valid eigenvalue
2331  if (eigenValue > 0) {
2332  // Really want the root of the eigen value
2333  eigenValue = 3. * sqrt(eigenValue);
2334 
2335  // Recover the eigenvector
2336  const std::vector<double>& eigenVector = pca->getEigenVectors()[dimIdx];
2337 
2338  // Set the first point
2339  double xl = avePosition[0] - 0.5 * eigenValue * eigenVector[0];
2340  double yl = avePosition[1] - 0.5 * eigenValue * eigenVector[1];
2341  double zl = avePosition[2] - 0.5 * eigenValue * eigenVector[2];
2342 
2343  pl.SetPoint(0, xl, yl, zl);
2344  pmrk.SetPoint(pmrkIdx++, xl, yl, zl);
2345 
2346  // Set the second point
2347  double xu = avePosition[0] + 0.5 * eigenValue * eigenVector[0];
2348  double yu = avePosition[1] + 0.5 * eigenValue * eigenVector[1];
2349  double zu = avePosition[2] + 0.5 * eigenValue * eigenVector[2];
2350 
2351  pl.SetPoint(1, xu, yu, zu);
2352  pmrk.SetPoint(pmrkIdx++, xu, yu, zu);
2353  }
2354  }
2355 
2356  // By convention we will have drawn the "best" axis first
2357  if (recoOpt->fBestPCAAxisOnly) break;
2358 
2359  pcaIdx++;
2360  }
2361  }
2362  }
2363 
2364  // Now let's loop over daughters and call drawing routine for them
2365  if (pfPart->NumDaughters() > 0) {
2366  depth++;
2367 
2368  // std::string indent(depth, ' ');
2369 
2370  // std::cout << indent << "-drawPFParticle3D--> pfPart idx: " << pfPart->Self() << ", daughter list size: " << pfPart->Daughters().size() << std::endl;
2371 
2372  for (const auto& daughterIdx : pfPart->Daughters()) {
2373  DrawPFParticle3D(pfParticleVec.at(daughterIdx),
2374  pfParticleVec,
2375  spacePointVec,
2376  edgeAssnsVec,
2377  spacePointAssnVec,
2378  edgeSPAssnVec,
2379  spHitAssnVec,
2380  trackAssnVec,
2381  pcAxisAssnVec,
2382  cosmicTagAssnVec,
2383  depth,
2384  view);
2385  }
2386  }
2387 
2388  return;
2389  }
2390 
2391  //......................................................................
2393  {
2395 
2396  if (recoOpt->fDrawEdges < 1) return;
2397 
2398  // The plan is to loop over the list of possible particles
2399  for (size_t imod = 0; imod < recoOpt->fEdgeLabels.size(); ++imod) {
2400  art::InputTag const which = recoOpt->fEdgeLabels[imod];
2401 
2402  // Start off by recovering our 3D Clusters for this label
2403  std::vector<art::Ptr<recob::Edge>> edgeVec;
2404  GetEdges(evt, which, edgeVec);
2405 
2406  mf::LogDebug("RecoBaseDrawer")
2407  << "RecoBaseDrawer: number Edges to draw: " << edgeVec.size() << std::endl;
2408 
2409  if (!edgeVec.empty()) {
2410  // Get the space points created by the PFParticle producer
2411  std::vector<art::Ptr<recob::SpacePoint>> spacePointVec;
2412  GetSpacePoints(evt, which, spacePointVec);
2413 
2414  // First draw the space points (all of them), then circle back on the edges...
2415  int colorIdx(41); //2);
2416 
2417  TPolyMarker3D& pm = view->AddPolyMarker3D(
2418  spacePointVec.size(), colorIdx, kFullDotMedium, 0.5); //kFullDotLarge, 0.5);
2419 
2420  for (const auto& spacePoint : spacePointVec) {
2421  TVector3 spPosition(spacePoint->XYZ()[0], spacePoint->XYZ()[1], spacePoint->XYZ()[2]);
2422 
2423  pm.SetNextPoint(spPosition[0], spPosition[1], spPosition[2]);
2424  }
2425 
2426  // Now draw the edges
2427  for (const auto& edge : edgeVec) {
2428  art::Ptr<recob::SpacePoint> firstSP = spacePointVec.at(edge->FirstPointID());
2429  art::Ptr<recob::SpacePoint> secondSP = spacePointVec.at(edge->SecondPointID());
2430 
2431  if (firstSP->ID() != edge->FirstPointID() || secondSP->ID() != edge->SecondPointID()) {
2432  mf::LogDebug("RecoBaseDrawer")
2433  << "Edge: Space point index mismatch, first: " << firstSP->ID() << ", "
2434  << edge->FirstPointID() << ", second: " << secondSP->ID() << ", "
2435  << edge->SecondPointID() << std::endl;
2436  continue;
2437  }
2438 
2439  TVector3 startPoint(firstSP->XYZ()[0], firstSP->XYZ()[1], firstSP->XYZ()[2]);
2440  TVector3 endPoint(secondSP->XYZ()[0], secondSP->XYZ()[1], secondSP->XYZ()[2]);
2441  TVector3 lineVec(endPoint - startPoint);
2442 
2443  double length = lineVec.Mag();
2444 
2445  if (length == 0.) {
2446  // std::cout << "Edge length is zero, index 1: " << edge->FirstPointID() << ", index 2: " << edge->SecondPointID() << std::endl;
2447  continue;
2448  }
2449 
2450  // Get a polyline object to draw from the first to the second space point
2451  // TPolyLine3D& pl = view->AddPolyLine3D(2, colorIdx, 1, 1); //4, 1);
2452  //
2453  // pl.SetPoint(0, startPoint[0], startPoint[1], startPoint[2]);
2454  // pl.SetPoint(1, endPoint[0], endPoint[1], endPoint[2]);
2455  TPolyMarker3D& fakeLine = view->AddPolyMarker3D(10, 5, kFullDotMedium, 1.0);
2456 
2457  lineVec.SetMag(1.);
2458 
2459  for (int idx = 1; idx <= 10; idx++) {
2460  TVector3 plotPoint = startPoint + 0.1 * double(idx) * length * lineVec;
2461 
2462  fakeLine.SetNextPoint(plotPoint[0], plotPoint[1], plotPoint[2]);
2463  }
2464  }
2465  }
2466  }
2467 
2468  // Draw any associated Extreme Points
2469  for (size_t imod = 0; imod < recoOpt->fExtremePointLabels.size(); ++imod) {
2470  art::InputTag const which = recoOpt->fExtremePointLabels[imod];
2471 
2472  // Start off by recovering our 3D Clusters for this label
2473  std::vector<art::Ptr<recob::SpacePoint>> spacePointVec;
2474  GetSpacePoints(evt, which, spacePointVec);
2475 
2476  mf::LogDebug("RecoBaseDrawer")
2477  << "RecoBaseDrawer: number Extreme points to draw: " << spacePointVec.size() << std::endl;
2478 
2479  if (!spacePointVec.empty()) {
2480  // First draw the space points (all of them), then circle back on the edges...
2481  int colorIdx(kYellow);
2482 
2483  TPolyMarker3D& pm = view->AddPolyMarker3D(
2484  spacePointVec.size(), colorIdx, kFullDotLarge, 1.0); //kFullDotLarge, 0.5);
2485 
2486  for (const auto& spacePoint : spacePointVec) {
2487  TVector3 spPosition(spacePoint->XYZ()[0], spacePoint->XYZ()[1], spacePoint->XYZ()[2]);
2488 
2489  pm.SetNextPoint(spPosition[0], spPosition[1], spPosition[2]);
2490  }
2491  }
2492  }
2493 
2494  return;
2495  }
2496 
2497  //......................................................................
2499  {
2502 
2503  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
2504 
2505  // annoying for now, but have to have multiple copies of basically the
2506  // same code to draw prongs, showers and tracks so that we can use
2507  // the art::Assns to get the hits and clusters.
2508 
2509  // Tracks.
2510 
2511  if (recoOpt->fDrawTracks > 2) {
2512  for (size_t imod = 0; imod < recoOpt->fTrackLabels.size(); ++imod) {
2513  art::InputTag which = recoOpt->fTrackLabels[imod];
2514  art::View<recob::Track> trackView;
2515  GetTracks(evt, which, trackView);
2516  if (!trackView.isValid())
2517  continue; //Prevent potential segmentation fault if no tracks found. aoliv23@lsu.edu
2518 
2520 
2521  trackView.fill(trackVec);
2522 
2523  art::InputTag const cosmicTagLabel(
2524  recoOpt->fCosmicTagLabels.size() > imod ? recoOpt->fCosmicTagLabels[imod] : "");
2525  art::FindMany<anab::CosmicTag> cosmicTagAssnVec(trackVec, evt, cosmicTagLabel);
2526 
2527  for (const auto& track : trackVec) {
2528  int color = evd::kColor[track.key() % evd::kNCOLS];
2529  int marker = kFullDotLarge;
2530  float size = 2.0;
2531 
2532  // Check if a CosmicTag object is available
2533 
2534  // Recover cosmic tag info if any
2535  if (cosmicTagAssnVec.isValid()) {
2536  std::vector<const anab::CosmicTag*> tkCosmicTagVec = cosmicTagAssnVec.at(track.key());
2537 
2538  if (!tkCosmicTagVec.empty()) {
2539  const anab::CosmicTag* cosmicTag = tkCosmicTagVec.front();
2540 
2541  // If tagged as Cosmic then neutralize the color
2542  if (cosmicTag->CosmicScore() > 0.6) {
2543  color = 14;
2544  size = 0.5;
2545  }
2546  }
2547  }
2548 
2549  // Draw track using only embedded information.
2550 
2551  DrawTrack3D(*track, view, color, marker, size);
2552  }
2553  }
2554  }
2555 
2556  // Showers.
2557 
2558  if (recoOpt->fDrawShowers != 0) {
2559  for (size_t imod = 0; imod < recoOpt->fShowerLabels.size(); ++imod) {
2560  art::InputTag which = recoOpt->fShowerLabels[imod];
2562  GetShowers(evt, which, shower);
2563 
2564  for (size_t s = 0; s < shower.vals().size(); ++s) {
2565  const recob::Shower* pshower = shower.vals().at(s);
2566  int color = pshower->ID();
2567  DrawShower3D(*pshower, color, view);
2568  }
2569  }
2570  }
2571 
2572  return;
2573  }
2574 
2575  //......................................................................
2577  evdb::View3D* view,
2578  int color,
2579  int marker,
2580  float size)
2581  {
2582  // Get options.
2584 
2585  if (recoOpt->fDrawTrackSpacePoints) {
2586  // Use brute force to find the module label and index of this
2587  // track, so that we can find associated space points and draw
2588  // them.
2590  //std::vector<art::Handle<std::vector<recob::Track>>> handles;
2591  //evt->getManyByType(handles);
2592  auto handles = evt->getMany<std::vector<recob::Track>>();
2593 
2594  for (auto ih : handles) {
2595  const art::Handle<std::vector<recob::Track>> handle = ih;
2596 
2597  if (handle.isValid()) {
2598  const std::string& which = handle.provenance()->moduleLabel();
2599  art::FindManyP<recob::SpacePoint> fmsp(handle, *evt, which);
2600 
2601  if (fmsp.isValid() && fmsp.size() > 0) {
2602  int n = handle->size();
2603  float spSize = 0.5 * size;
2604 
2605  for (int i = 0; i < n; ++i) {
2606  art::Ptr<recob::Track> p(handle, i);
2607  if (&*p == &track) {
2608  std::vector<art::Ptr<recob::SpacePoint>> spts = fmsp.at(i);
2609  fSpacePointDrawer->Draw(spts, view, color, marker, spSize);
2610  }
2611  }
2612  }
2613  }
2614  }
2615  }
2616 
2617  if (recoOpt->fDrawTrackTrajectoryPoints) {
2618  // Draw trajectory points.
2619  int np = track.NumberTrajectoryPoints();
2620 
2621  int lineSize = size;
2622 
2623  if (lineSize < 1) lineSize = 1;
2624 
2625  // Make and fill a special polymarker for the head of the track
2626  //TPolyMarker3D& pmStart = view->AddPolyMarker3D(1, color, 4, 3);
2627  TPolyMarker3D& pmStart = view->AddPolyMarker3D(1, 0, marker, 2. * size);
2628 
2629  const auto& firstPos = track.LocationAtPoint(0);
2630  pmStart.SetPoint(0, firstPos.X(), firstPos.Y(), firstPos.Z());
2631 
2632  // Make and fill a polymarker.
2633  TPolyMarker3D& pm = view->AddPolyMarker3D(track.CountValidPoints(), color, 1, 3);
2634 
2635  for (int p = 0; p < np; ++p) {
2636  if (!track.HasValidPoint(p)) continue;
2637 
2638  const auto& pos = track.LocationAtPoint(p);
2639  pm.SetPoint(p, pos.X(), pos.Y(), pos.Z());
2640  }
2641 
2642  // As we are a track, should we not be drawing a line here?
2643  TPolyLine3D& pl = view->AddPolyLine3D(track.CountValidPoints(), color, lineSize, 7);
2644 
2645  for (int p = 0; p < np; ++p) {
2646  if (!track.HasValidPoint(p)) continue;
2647 
2648  const auto pos = track.LocationAtPoint(p);
2649 
2650  pl.SetPoint(p, pos.X(), pos.Y(), pos.Z());
2651  }
2652 
2653  if (recoOpt->fDrawTrackTrajectoryPoints > 4) {
2654  // Can we add the track direction at each point?
2655  // This won't work for the last point... but let's try
2656  auto startPos = track.LocationAtPoint(0);
2657  auto startDir = track.DirectionAtPoint(0);
2658 
2659  for (int p = 1; p < np; ++p) {
2660  if (!track.HasValidPoint(p)) continue;
2661 
2662  TPolyLine3D& pl = view->AddPolyLine3D(2, (color + 1) % evd::kNCOLS, size, 7); //1, 3);
2663 
2664  auto nextPos = track.LocationAtPoint(p);
2665  auto deltaPos = nextPos - startPos;
2666  double arcLen = deltaPos.Dot(
2667  startDir); // arc len to plane containing next point perpendicular to current point dir
2668 
2669  if (arcLen < 0.) arcLen = 3.;
2670 
2671  auto endPoint = startPos + arcLen * startDir;
2672 
2673  pl.SetPoint(0, startPos.X(), startPos.Y(), startPos.Z());
2674  pl.SetPoint(1, endPoint.X(), endPoint.Y(), endPoint.Z());
2675 
2676  startPos = nextPos;
2677  startDir = track.DirectionAtPoint(p);
2678  }
2679  }
2680  }
2681 
2682  return;
2683  }
2684 
2685  //......................................................................
2687  {
2688  // Use brute force to find the module label and index of this
2689  // shower, so that we can find associated space points and draw
2690  // them.
2691  // B. Baller: Catch an exception if there are no space points and draw a cone instead.
2692 
2694  //std::vector<art::Handle<std::vector<recob::Shower>>> handles;
2695  //evt->getManyByType(handles);
2696  auto handles = evt->getMany<std::vector<recob::Shower>>();
2697 
2698  bool noSpts = false;
2699 
2700  for (auto ih : handles) {
2701  const art::Handle<std::vector<recob::Shower>> handle = ih;
2702 
2703  if (handle.isValid()) {
2704 
2705  const std::string& which = handle.provenance()->moduleLabel();
2706  art::FindManyP<recob::SpacePoint> fmsp(handle, *evt, which);
2707 
2708  int n = handle->size();
2709  for (int i = 0; i < n; ++i) {
2710  art::Ptr<recob::Shower> p(handle, i);
2711  if (&*p == &shower) {
2712  // BB catch if no space points
2713  std::vector<art::Ptr<recob::SpacePoint>> spts;
2714  try {
2715  spts = fmsp.at(i);
2716  fSpacePointDrawer->Draw(spts, view, color);
2717  }
2718  catch (...) {
2719  noSpts = true;
2720  continue;
2721  } // catch
2722  } // shower
2723  } // i
2724  } // ih
2725  }
2726 
2727  if (noSpts && shower.has_length() && shower.has_open_angle()) {
2728  std::cout << "No space points associated with the shower. Drawing a cone instead\n";
2729  color = kRed;
2730  auto& dedx = shower.dEdx();
2731  if (!dedx.empty()) {
2732  double dedxAve = 0;
2733  for (auto& dedxInPln : dedx)
2734  dedxAve += dedxInPln;
2735  dedxAve /= (double)dedx.size();
2736  // Use blue for ~1 MIP
2737  color = kBlue;
2738  // use green for ~2 MIP
2739  if (dedxAve > 3 && dedxAve < 5) color = kGreen;
2740  }
2741  double radius = shower.Length() * shower.OpenAngle();
2742  TVector3 startPos = shower.ShowerStart();
2743  TVector3 endPos = startPos + shower.Length() * shower.Direction();
2744  auto coneRim = Circle3D(endPos, shower.Direction(), radius);
2745  TPolyLine3D& pl = view->AddPolyLine3D(coneRim.size(), color, 2, 0);
2746  for (unsigned short ipt = 0; ipt < coneRim.size(); ++ipt) {
2747  auto& pt = coneRim[ipt];
2748  pl.SetPoint(ipt, pt[0], pt[1], pt[2]);
2749  }
2750  // Draw a line from the start position to each point on the rim
2751  for (unsigned short ipt = 0; ipt < coneRim.size(); ++ipt) {
2752  TPolyLine3D& panel = view->AddPolyLine3D(2, color, 2, 0);
2753  panel.SetPoint(0, startPos.X(), startPos.Y(), startPos.Z());
2754  panel.SetPoint(1, coneRim[ipt][0], coneRim[ipt][1], coneRim[ipt][2]);
2755  } // ipt
2756 
2757  } // no space points
2758 
2759  return;
2760  }
2761 
2762  //......................................................................
2763  std::vector<std::array<double, 3>> RecoBaseDrawer::Circle3D(const TVector3& centerPos,
2764  const TVector3& axisDir,
2765  const double& radius)
2766  {
2767  // B. Baller Create a polyline circle in 3D
2768 
2769  // Make the rotation matrix to transform into the circle coordinate system
2770  TRotation r;
2771  r.RotateX(axisDir.X());
2772  r.RotateY(axisDir.Y());
2773  r.RotateZ(axisDir.Z());
2774  constexpr unsigned short nRimPts = 16;
2775  std::vector<std::array<double, 3>> rimPts(nRimPts + 1);
2776  for (unsigned short iang = 0; iang < nRimPts; ++iang) {
2777  double rimAngle = iang * 2 * M_PI / (float)nRimPts;
2778  TVector3 rim = {0, 0, 1};
2779  rim.SetX(radius * cos(rimAngle));
2780  rim.SetY(radius * sin(rimAngle));
2781  rim.SetZ(0);
2782  rim.Transform(r);
2783  rim += centerPos;
2784  for (unsigned short ixyz = 0; ixyz < 3; ++ixyz)
2785  rimPts[iang][ixyz] = rim[ixyz];
2786  } // iang
2787  // close the circle
2788  rimPts[nRimPts] = rimPts[0];
2789  return rimPts;
2790  } // PolyLineCircle
2791 
2792  //......................................................................
2794  {
2797 
2798  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
2799 
2800  if (recoOpt->fDrawVertices != 0) {
2801 
2802  for (size_t imod = 0; imod < recoOpt->fVertexLabels.size(); ++imod) {
2803  art::InputTag const which = recoOpt->fVertexLabels[imod];
2804 
2806  GetVertices(evt, which, vertex);
2807 
2808  art::FindManyP<recob::Track> fmt(vertex, evt, which);
2809  art::FindManyP<recob::Shower> fms(vertex, evt, which);
2810 
2811  for (size_t v = 0; v < vertex.size(); ++v) {
2812 
2813  if (fmt.isValid()) {
2814  std::vector<art::Ptr<recob::Track>> tracks = fmt.at(v);
2815 
2816  // grab the Prongs from the vertex and draw those
2817  for (size_t t = 0; t < tracks.size(); ++t)
2818  DrawTrack3D(*(tracks[t]), view, vertex[v]->ID());
2819  }
2820 
2821  if (fms.isValid()) {
2822  std::vector<art::Ptr<recob::Shower>> showers = fms.at(v);
2823 
2824  for (size_t s = 0; s < showers.size(); ++s)
2825  DrawShower3D(*(showers[s]), vertex[v]->ID(), view);
2826  }
2827 
2828  double xyz[3] = {0.};
2829  vertex[v]->XYZ(xyz);
2830  TPolyMarker3D& pm =
2831  view->AddPolyMarker3D(1, evd::kColor[vertex[v]->ID() % evd::kNCOLS], 29, 6);
2832  pm.SetPoint(0, xyz[0], xyz[1], xyz[2]);
2833 
2834  } // end loop over vertices to draw from this label
2835  } // end loop over vertex module lables
2836  } // end if we are drawing vertices
2837 
2838  return;
2839  }
2840 
2841  //......................................................................
2843  {
2846 
2847  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
2848  if (recoOpt->fDrawEvents != 0) {
2849 
2850  for (size_t imod = 0; imod < recoOpt->fEventLabels.size(); ++imod) {
2851  art::InputTag const which = recoOpt->fEventLabels[imod];
2852 
2854  GetEvents(evt, which, event);
2855 
2856  if (event.size() < 1) continue;
2857 
2858  art::FindManyP<recob::Vertex> fmvp(event, evt, which);
2859  art::FindMany<recob::Vertex> fmv(event, evt, which);
2860 
2861  for (size_t e = 0; e < event.size(); ++e) {
2862 
2863  // grab the vertices for this event
2864  std::vector<art::Ptr<recob::Vertex>> vertex = fmvp.at(e);
2865 
2866  if (vertex.size() < 1) continue;
2867 
2868  art::FindManyP<recob::Track> fmt(vertex, evt, recoOpt->fVertexLabels[0]);
2869  art::FindManyP<recob::Shower> fms(vertex, evt, recoOpt->fVertexLabels[0]);
2870 
2871  for (size_t v = 0; v < vertex.size(); ++v) {
2872 
2874  // right now assume there is only 1 in the list
2875  std::vector<art::Ptr<recob::Track>> tracks = fmt.at(v);
2876  std::vector<art::Ptr<recob::Shower>> showers = fms.at(v);
2877 
2878  // grab the Prongs from the vertex and draw those
2879  for (size_t t = 0; t < tracks.size(); ++t)
2880  DrawTrack3D(*(tracks[t]), view, event[e]->ID());
2881 
2882  for (size_t s = 0; s < showers.size(); ++s)
2883  DrawShower3D(*(showers[s]), event[e]->ID(), view);
2884 
2885  } // end loop over vertices from this event
2886 
2887  double xyz[3] = {0.};
2888  std::vector<const recob::Vertex*> vts = fmv.at(e);
2889 
2890  event[e]->PrimaryVertex(vts)->XYZ(xyz);
2891  TPolyMarker3D& pm =
2892  view->AddPolyMarker3D(1, evd::kColor[event[e]->ID() % evd::kNCOLS], 29, 6);
2893  pm.SetPoint(0, xyz[0], xyz[1], xyz[2]);
2894 
2895  } // end loop over events
2896  } // end loop over event module lables
2897  } // end if we are drawing events
2898 
2899  return;
2900  }
2901  //......................................................................
2903  {
2906 
2907  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
2908  if (recoOpt->fDrawSlices < 1) return;
2909  if (recoOpt->fDrawSliceSpacePoints < 1) return;
2910  for (size_t imod = 0; imod < recoOpt->fSliceLabels.size(); ++imod) {
2911  art::InputTag const which = recoOpt->fSliceLabels[imod];
2913  GetSlices(evt, which, slices);
2914  if (slices.size() < 1) continue;
2915  art::FindManyP<recob::SpacePoint> fmsp(slices, evt, which);
2916  for (size_t isl = 0; isl < slices.size(); ++isl) {
2917  int slcID = std::abs(slices[isl]->ID());
2918  int color = evd::kColor[slcID % evd::kNCOLS];
2919  std::vector<art::Ptr<recob::SpacePoint>> spts = fmsp.at(isl);
2920  fSpacePointDrawer->Draw(spts, view, color, kFullDotLarge, 2);
2921  }
2922  }
2923  }
2924  //......................................................................
2926  detinfo::DetectorClocksData const& clockData,
2927  detinfo::DetectorPropertiesData const& detProp,
2929  evdb::View2D* view)
2930  {
2934 
2935  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
2936  if (recoOpt->fDrawOpFlashes == 0) return;
2937 
2938  double minx = 1e9;
2939  double maxx = -1e9;
2940  for (auto const& tpc : geo->Iterate<geo::TPCGeo>(geo::CryostatID{0})) {
2941  auto const world = tpc.GetCenter();
2942  if (minx > world.X() - tpc.HalfWidth()) minx = world.X() - tpc.HalfWidth();
2943  if (maxx < world.X() + tpc.HalfWidth()) maxx = world.X() + tpc.HalfWidth();
2944  }
2945 
2946  geo::PlaneID const planeID{rawOpt->fCryostat, rawOpt->fTPC, 0};
2947 
2948  for (size_t imod = 0; imod < recoOpt->fOpFlashLabels.size(); ++imod) {
2949  const art::InputTag which = recoOpt->fOpFlashLabels[imod];
2950 
2952  GetOpFlashes(evt, which, opflashes);
2953 
2954  if (opflashes.size() < 1) continue;
2955 
2956  int NFlashes = opflashes.size();
2957 
2958  // project each seed into this view
2959  for (int iof = 0; iof < NFlashes; ++iof) {
2960 
2961  if (opflashes[iof]->TotalPE() < recoOpt->fFlashMinPE) continue;
2962  if (opflashes[iof]->Time() < recoOpt->fFlashTMin) continue;
2963  if (opflashes[iof]->Time() > recoOpt->fFlashTMax) continue;
2964 
2965  double YCentre = opflashes[iof]->YCenter();
2966  double YHalfWidth = opflashes[iof]->YWidth();
2967  double ZCentre = opflashes[iof]->ZCenter();
2968  double ZHalfWidth = opflashes[iof]->ZWidth();
2969 
2970  int Colour = evd::kColor[(iof) % evd::kNCOLS];
2971 
2972  if (proj == evd::kXY) {
2973  TBox& b1 = view->AddBox(YCentre - YHalfWidth, minx, YCentre + YHalfWidth, maxx);
2974  b1.SetFillStyle(3004 + (iof % 3));
2975  b1.SetFillColor(Colour);
2976  }
2977  else if (proj == evd::kXZ) {
2978  float xflash =
2979  detProp.ConvertTicksToX(opflashes[iof]->Time() / sampling_rate(clockData) * 1e3 +
2980  detProp.GetXTicksOffset(planeID),
2981  planeID);
2982  TLine& line = view->AddLine(ZCentre - ZHalfWidth, xflash, ZCentre + ZHalfWidth, xflash);
2983  line.SetLineWidth(2);
2984  line.SetLineStyle(2);
2985  line.SetLineColor(Colour);
2986  }
2987  else if (proj == evd::kYZ) {
2988  TBox& b1 = view->AddBox(
2989  ZCentre - ZHalfWidth, YCentre - YHalfWidth, ZCentre + ZHalfWidth, YCentre + YHalfWidth);
2990  b1.SetFillStyle(3004 + (iof % 3));
2991  b1.SetFillColor(Colour);
2992  view->AddMarker(ZCentre, YCentre, Colour, 4, 1.5);
2993  }
2994 
2995  } // Flashes with this label
2996  } // Vector of OpFlash labels
2997  }
2998  //......................................................................
3001  evdb::View2D* view,
3002  int marker)
3003  {
3004  for (size_t v = 0; v < vertex.size(); ++v) {
3005 
3006  double xyz[3] = {0.};
3007  vertex[v]->XYZ(xyz);
3008 
3009  int color = evd::kColor[vertex[v]->ID() % evd::kNCOLS];
3010 
3011  if (proj == evd::kXY) {
3012  TMarker& strt = view->AddMarker(xyz[1], xyz[0], color, marker, 1.0);
3013  strt.SetMarkerColor(color);
3014  }
3015  else if (proj == evd::kXZ) {
3016  TMarker& strt = view->AddMarker(xyz[2], xyz[0], color, marker, 1.0);
3017  strt.SetMarkerColor(color);
3018  }
3019  else if (proj == evd::kYZ) {
3020  TMarker& strt = view->AddMarker(xyz[2], xyz[1], color, marker, 1.0);
3021  strt.SetMarkerColor(color);
3022  }
3023  }
3024  }
3026  {
3030 
3031  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
3032  if (recoOpt->fDrawVertices == 0) return;
3033 
3034  for (size_t imod = 0; imod < recoOpt->fVertexLabels.size(); ++imod) {
3035  art::InputTag const which = recoOpt->fVertexLabels[imod];
3036 
3038  GetVertices(evt, which, vertex);
3039  VertexOrtho(vertex, proj, view, 24);
3040 
3041  //GetVertices(evt, art::InputTag(which.label(), "kink", which.process()), vertex);
3042  //VertexOrtho(vertex, proj, view, 27);
3043 
3044  //GetVertices(evt, art::InputTag(which.label(), "node", which.process()), vertex);
3045  //VertexOrtho(vertex, proj, view, 22);
3046  }
3047  return;
3048  }
3049 
3050  //......................................................................
3053  double msize,
3054  evdb::View2D* view)
3055  {
3058 
3059  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
3060 
3061  std::vector<art::InputTag> labels;
3062  if (recoOpt->fDrawSpacePoints != 0) {
3063  for (size_t imod = 0; imod < recoOpt->fSpacePointLabels.size(); ++imod)
3064  labels.push_back(recoOpt->fSpacePointLabels[imod]);
3065  }
3066 
3067  for (size_t imod = 0; imod < labels.size(); ++imod) {
3068  art::InputTag const which = labels[imod];
3069 
3070  std::vector<art::Ptr<recob::SpacePoint>> spts;
3071  GetSpacePoints(evt, which, spts);
3072  int color = imod;
3073 
3074  DrawSpacePointOrtho(spts, color, proj, msize, view);
3075  }
3076 
3077  return;
3078  }
3079 
3080  //......................................................................
3083  double msize,
3084  evdb::View2D* view)
3085  {
3088 
3089  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
3090  if (recoOpt->fDrawPFParticles < 1) return;
3091 
3092  // The plan is to loop over the list of possible particles
3093  for (size_t imod = 0; imod < recoOpt->fPFParticleLabels.size(); ++imod) {
3094  art::InputTag const which = recoOpt->fPFParticleLabels[imod];
3095 
3096  // Start off by recovering our 3D Clusters for this label
3097  art::PtrVector<recob::PFParticle> pfParticleVec;
3098  GetPFParticles(evt, which, pfParticleVec);
3099 
3100  // Make sure we have some clusters
3101  if (pfParticleVec.size() < 1) continue;
3102 
3103  // Add the relations to recover associations cluster hits
3104  art::FindMany<recob::SpacePoint> spacePointAssnVec(pfParticleVec, evt, which);
3105 
3106  // If no valid space point associations then nothing to do
3107  if (!spacePointAssnVec.isValid()) continue;
3108 
3109  // Need the PCA info as well
3110  art::FindMany<recob::PCAxis> pcAxisAssnVec(pfParticleVec, evt, which);
3111 
3112  if (!pcAxisAssnVec.isValid()) continue;
3113 
3114  // Commence looping over possible clusters
3115  for (size_t idx = 0; idx < pfParticleVec.size(); idx++) {
3116  // Recover cluster
3117  const art::Ptr<recob::PFParticle> pfParticle(pfParticleVec.at(idx));
3118 
3119  // Drawing will be done recursively down the chain of hieirarchy... so we want to begin
3120  // with only "primary" particles, if we find one that isn't then we skip
3121  if (!pfParticle->IsPrimary()) continue;
3122 
3123  // Call the recursive drawing routine
3125  pfParticle, pfParticleVec, spacePointAssnVec, pcAxisAssnVec, 0, proj, view);
3126  }
3127  }
3128 
3129  return;
3130  }
3131 
3133  const art::Ptr<recob::PFParticle>& pfPart,
3134  const art::PtrVector<recob::PFParticle>& pfParticleVec,
3135  const art::FindMany<recob::SpacePoint>& spacePointAssnVec,
3136  const art::FindMany<recob::PCAxis>& pcAxisAssnVec,
3137  int depth,
3139  evdb::View2D* view)
3140  {
3142 
3143  // First let's draw the hits associated to this cluster
3144  const std::vector<const recob::SpacePoint*>& hitsVec(spacePointAssnVec.at(pfPart->Self()));
3145 
3146  // Use the particle ID to determine the color to draw the points
3147  // Ok, this is what we would like to do eventually but currently all particles are the same...
3148  // int colorIdx = evd::Style::ColorFromPDG(pfPart->PdgCode());
3149  int colorIdx = evd::kColor[pfPart->Self() % evd::kNCOLS];
3150 
3151  if (!hitsVec.empty()) {
3152  std::vector<const recob::SpacePoint*> hitPosVec;
3153  std::vector<const recob::SpacePoint*> skeletonPosVec;
3154  std::vector<const recob::SpacePoint*> skelEdgePosVec;
3155  std::vector<const recob::SpacePoint*> edgePosVec;
3156  std::vector<const recob::SpacePoint*> seedPosVec;
3157  std::vector<const recob::SpacePoint*> pairPosVec;
3158 
3159  for (const auto& spacePoint : hitsVec) {
3160  if (spacePoint->Chisq() > 0.)
3161  hitPosVec.push_back(spacePoint);
3162  else if (spacePoint->Chisq() == -1.)
3163  skeletonPosVec.push_back(spacePoint);
3164  else if (spacePoint->Chisq() == -3.)
3165  skelEdgePosVec.push_back(spacePoint);
3166  else if (spacePoint->Chisq() == -4.)
3167  seedPosVec.push_back(spacePoint);
3168  else if (spacePoint->Chisq() > -10.)
3169  edgePosVec.push_back(spacePoint);
3170  else
3171  pairPosVec.push_back(spacePoint);
3172  }
3173 
3174  int hitIdx(0);
3175 
3176  if (!recoOpt->fSkeletonOnly) {
3177  TPolyMarker& pm1 = view->AddPolyMarker(hitPosVec.size(), colorIdx, kFullDotMedium, 1);
3178  for (const auto* spacePoint : hitPosVec) {
3179  const double* pos = spacePoint->XYZ();
3180 
3181  if (proj == evd::kXY)
3182  pm1.SetPoint(hitIdx++, pos[0], pos[1]);
3183  else if (proj == evd::kXZ)
3184  pm1.SetPoint(hitIdx++, pos[2], pos[0]);
3185  else if (proj == evd::kYZ)
3186  pm1.SetPoint(hitIdx++, pos[2], pos[1]);
3187  }
3188 
3189  hitIdx = 0;
3190 
3191  TPolyMarker& pm2 = view->AddPolyMarker(edgePosVec.size(), 28, kFullDotMedium, 1);
3192  for (const auto* spacePoint : edgePosVec) {
3193  const double* pos = spacePoint->XYZ();
3194 
3195  if (proj == evd::kXY)
3196  pm2.SetPoint(hitIdx++, pos[0], pos[1]);
3197  else if (proj == evd::kXZ)
3198  pm2.SetPoint(hitIdx++, pos[2], pos[0]);
3199  else if (proj == evd::kYZ)
3200  pm2.SetPoint(hitIdx++, pos[2], pos[1]);
3201  }
3202 
3203  hitIdx = 0;
3204 
3205  TPolyMarker& pm3 = view->AddPolyMarker(pairPosVec.size(), 2, kFullDotMedium, 1);
3206  for (const auto* spacePoint : pairPosVec) {
3207  const double* pos = spacePoint->XYZ();
3208 
3209  if (proj == evd::kXY)
3210  pm3.SetPoint(hitIdx++, pos[0], pos[1]);
3211  else if (proj == evd::kXZ)
3212  pm3.SetPoint(hitIdx++, pos[2], pos[0]);
3213  else if (proj == evd::kYZ)
3214  pm3.SetPoint(hitIdx++, pos[2], pos[1]);
3215  }
3216  }
3217 
3218  hitIdx = 0;
3219 
3220  TPolyMarker& pm4 = view->AddPolyMarker(skeletonPosVec.size(), 1, kFullDotMedium, 1);
3221  for (const auto* spacePoint : skeletonPosVec) {
3222  const double* pos = spacePoint->XYZ();
3223 
3224  if (proj == evd::kXY)
3225  pm4.SetPoint(hitIdx++, pos[0], pos[1]);
3226  else if (proj == evd::kXZ)
3227  pm4.SetPoint(hitIdx++, pos[2], pos[0]);
3228  else if (proj == evd::kYZ)
3229  pm4.SetPoint(hitIdx++, pos[2], pos[1]);
3230  }
3231 
3232  hitIdx = 0;
3233 
3234  TPolyMarker& pm5 = view->AddPolyMarker(skelEdgePosVec.size(), 3, kFullDotMedium, 1);
3235  for (const auto* spacePoint : skelEdgePosVec) {
3236  const double* pos = spacePoint->XYZ();
3237 
3238  if (proj == evd::kXY)
3239  pm5.SetPoint(hitIdx++, pos[0], pos[1]);
3240  else if (proj == evd::kXZ)
3241  pm5.SetPoint(hitIdx++, pos[2], pos[0]);
3242  else if (proj == evd::kYZ)
3243  pm5.SetPoint(hitIdx++, pos[2], pos[1]);
3244  }
3245 
3246  hitIdx = 0;
3247 
3248  TPolyMarker& pm6 = view->AddPolyMarker(seedPosVec.size(), 6, kFullDotMedium, 1);
3249  for (const auto* spacePoint : seedPosVec) {
3250  const double* pos = spacePoint->XYZ();
3251 
3252  if (proj == evd::kXY)
3253  pm6.SetPoint(hitIdx++, pos[0], pos[1]);
3254  else if (proj == evd::kXZ)
3255  pm6.SetPoint(hitIdx++, pos[2], pos[0]);
3256  else if (proj == evd::kYZ)
3257  pm6.SetPoint(hitIdx++, pos[2], pos[1]);
3258  }
3259  }
3260 
3261  // Look up the PCA info
3262  if (pcAxisAssnVec.isValid()) {
3263  std::vector<const recob::PCAxis*> pcaVec(pcAxisAssnVec.at(pfPart->Self()));
3264 
3265  if (!pcaVec.empty()) {
3266  // For each axis we are going to draw a solid line between two points
3267  int numPoints(2);
3268  int lineWidth[2] = {3, 1};
3269  int lineStyle[2] = {1, 13};
3270  int lineColor[2] = {colorIdx, 18};
3271  int markStyle[2] = {4, 4};
3272  int pcaIdx(0);
3273 
3274  // The order of axes in the returned association vector is arbitrary... the "first" axis is
3275  // better and we can divine that by looking at the axis id's (the best will have been made first)
3276  if (pcaVec.size() > 1 && pcaVec.front()->getID() > pcaVec.back()->getID())
3277  std::reverse(pcaVec.begin(), pcaVec.end());
3278 
3279  for (const auto& pca : pcaVec) {
3280  // We need the mean position
3281  const double* avePosition = pca->getAvePosition();
3282 
3283  // Let's draw a marker at the interesting points
3284  int pmrkIdx(0);
3285  TPolyMarker& pmrk = view->AddPolyMarker(7, lineColor[pcaIdx], markStyle[pcaIdx], 1);
3286 
3287  if (proj == evd::kXY)
3288  pmrk.SetPoint(pmrkIdx++, avePosition[0], avePosition[1]);
3289  else if (proj == evd::kXZ)
3290  pmrk.SetPoint(pmrkIdx++, avePosition[2], avePosition[0]);
3291  else if (proj == evd::kYZ)
3292  pmrk.SetPoint(pmrkIdx++, avePosition[2], avePosition[1]);
3293 
3294  // Loop over pca dimensions
3295  for (int dimIdx = 0; dimIdx < 3; dimIdx++) {
3296  // Oh please oh please give me an instance of a poly line...
3297  TPolyLine& pl =
3298  view->AddPolyLine(numPoints, lineColor[pcaIdx], lineWidth[pcaIdx], lineStyle[pcaIdx]);
3299 
3300  // We will use the eigen value to give the length of the line we're going to plot
3301  double eigenValue = pca->getEigenValues()[dimIdx];
3302 
3303  // Make sure a valid eigenvalue
3304  if (eigenValue > 0) {
3305  // Really want the root of the eigen value
3306  eigenValue = 3. * sqrt(eigenValue);
3307 
3308  // Recover the eigenvector
3309  const std::vector<double>& eigenVector = pca->getEigenVectors()[dimIdx];
3310 
3311  // Set the first point
3312  double xl = avePosition[0] - 0.5 * eigenValue * eigenVector[0];
3313  double yl = avePosition[1] - 0.5 * eigenValue * eigenVector[1];
3314  double zl = avePosition[2] - 0.5 * eigenValue * eigenVector[2];
3315 
3316  if (proj == evd::kXY) {
3317  pl.SetPoint(0, xl, yl);
3318  pmrk.SetPoint(pmrkIdx++, xl, yl);
3319  }
3320  else if (proj == evd::kXZ) {
3321  pl.SetPoint(0, zl, xl);
3322  pmrk.SetPoint(pmrkIdx++, zl, xl);
3323  }
3324  else if (proj == evd::kYZ) {
3325  pl.SetPoint(0, zl, yl);
3326  pmrk.SetPoint(pmrkIdx++, zl, yl);
3327  }
3328 
3329  // Set the second point
3330  double xu = avePosition[0] + 0.5 * eigenValue * eigenVector[0];
3331  double yu = avePosition[1] + 0.5 * eigenValue * eigenVector[1];
3332  double zu = avePosition[2] + 0.5 * eigenValue * eigenVector[2];
3333 
3334  if (proj == evd::kXY) {
3335  pl.SetPoint(1, xu, yu);
3336  pmrk.SetPoint(pmrkIdx++, xu, yu);
3337  }
3338  else if (proj == evd::kXZ) {
3339  pl.SetPoint(1, zu, xu);
3340  pmrk.SetPoint(pmrkIdx++, zu, xu);
3341  }
3342  else if (proj == evd::kYZ) {
3343  pl.SetPoint(1, zu, yu);
3344  pmrk.SetPoint(pmrkIdx++, zu, yu);
3345  }
3346  }
3347  }
3348 
3349  // By convention we will have drawn the "best" axis first
3350  if (recoOpt->fBestPCAAxisOnly) break;
3351 
3352  pcaIdx++;
3353  }
3354  }
3355  }
3356 
3357  // Now let's loop over daughters and call drawing routine for them
3358  if (pfPart->NumDaughters() > 0) {
3359  depth++;
3360 
3361  for (const auto& daughterIdx : pfPart->Daughters()) {
3362  DrawPFParticleOrtho(pfParticleVec.at(daughterIdx),
3363  pfParticleVec,
3364  spacePointAssnVec,
3365  pcAxisAssnVec,
3366  depth,
3367  proj,
3368  view);
3369  }
3370  }
3371 
3372  return;
3373  }
3374 
3375  //......................................................................
3378  double msize,
3379  evdb::View2D* view)
3380  {
3383 
3384  if (rawOpt->fDrawRawDataOrCalibWires < 1) return;
3385 
3386  // annoying for now, but have to have multiple copies of basically the
3387  // same code to draw prongs, showers and tracks so that we can use
3388  // the art::Assns to get the hits and clusters.
3389 
3390  // Tracks.
3391 
3392  if (recoOpt->fDrawTracks != 0) {
3393  for (size_t imod = 0; imod < recoOpt->fTrackLabels.size(); ++imod) {
3394  art::InputTag which = recoOpt->fTrackLabels[imod];
3396  GetTracks(evt, which, track);
3397 
3398  for (size_t t = 0; t < track.vals().size(); ++t) {
3399  const recob::Track* ptrack = track.vals().at(t);
3400  int color = ptrack->ID() & 65535;
3401 
3402  // Draw track using only embedded information.
3403 
3404  DrawTrackOrtho(*ptrack, color, proj, msize, view);
3405  }
3406  }
3407  }
3408 
3409  // Showers.
3410 
3411  if (recoOpt->fDrawShowers != 0) {
3412  for (size_t imod = 0; imod < recoOpt->fShowerLabels.size(); ++imod) {
3413  art::InputTag which = recoOpt->fShowerLabels[imod];
3415  GetShowers(evt, which, shower);
3416 
3417  for (size_t s = 0; s < shower.vals().size(); ++s) {
3418  const recob::Shower* pshower = shower.vals().at(s);
3419  int color = pshower->ID();
3420  DrawShowerOrtho(*pshower, color, proj, msize, view);
3421  }
3422  }
3423  }
3424 
3425  return;
3426  }
3427 
3428  //......................................................................
3430  int color,
3432  double msize,
3433  evdb::View2D* view,
3434  int mode)
3435  {
3436  // Get services.
3437 
3439 
3440  // Organize space points into separate collections according to the color
3441  // we want them to be.
3442  // If option If option fColorSpacePointsByChisq is false, this means
3443  // having a single collection with color inherited from the prong
3444  // (specified by the argument color).
3445 
3446  std::map<int, std::vector<art::Ptr<recob::SpacePoint>>> spmap; // Indexed by color.
3447 
3448  for (auto& pspt : spts) {
3449 
3450  // By default use event display palette.
3451 
3452  int spcolor = evd::kColor[color % evd::kNCOLS];
3453  if (mode == 1) { //shower hits
3454  spcolor = evd::kColor2[color % evd::kNCOLS];
3455  }
3456  // For rainbow effect, choose root colors in range [51,100].
3457  // We are using 100=best (red), 51=worst (blue).
3458 
3459  if (recoOpt->fColorSpacePointsByChisq) {
3460  spcolor = 100 - 2.5 * pspt->Chisq();
3461  if (spcolor < 51) spcolor = 51;
3462  if (spcolor > 100) spcolor = 100;
3463  }
3464  spmap[spcolor].push_back(pspt);
3465  }
3466 
3467  // Loop over colors.
3468  // Note that larger (=better) space points are plotted on
3469  // top for optimal visibility.
3470 
3471  for (auto icolor : spmap) {
3472  int spcolor = icolor.first;
3473  std::vector<art::Ptr<recob::SpacePoint>>& psps = icolor.second;
3474 
3475  // Make and fill a polymarker.
3476 
3477  TPolyMarker& pm = view->AddPolyMarker(psps.size(), spcolor, kFullCircle, msize);
3478  for (size_t s = 0; s < psps.size(); ++s) {
3479  const recob::SpacePoint& spt = *psps[s];
3480  const double* xyz = spt.XYZ();
3481  switch (proj) {
3482  case evd::kXY: pm.SetPoint(s, xyz[0], xyz[1]); break;
3483  case evd::kXZ: pm.SetPoint(s, xyz[2], xyz[0]); break;
3484  case evd::kYZ: pm.SetPoint(s, xyz[2], xyz[1]); break;
3485  default:
3486  throw cet::exception("RecoBaseDrawer")
3487  << __func__ << ": unknown projection #" << ((int)proj) << "\n";
3488  } // switch
3489  }
3490  }
3491 
3492  return;
3493  }
3494 
3495  //......................................................................
3497  int color,
3499  double msize,
3500  evdb::View2D* view)
3501  {
3502  // Get options.
3503 
3505 
3506  if (recoOpt->fDrawTrackSpacePoints) {
3507 
3508  // Use brute force to find the module label and index of this
3509  // track, so that we can find associated space points and draw
3510  // them.
3511 
3513  //std::vector<art::Handle<std::vector<recob::Track>>> handles;
3514  //evt->getManyByType(handles);
3515  auto handles = evt->getMany<std::vector<recob::Track>>();
3516  for (auto ih : handles) {
3517  const art::Handle<std::vector<recob::Track>> handle = ih;
3518  if (handle.isValid()) {
3519  const std::string& which = handle.provenance()->moduleLabel();
3520  art::FindManyP<recob::SpacePoint> fmsp(handle, *evt, which);
3521 
3522  int n = handle->size();
3523  for (int i = 0; i < n; ++i) {
3524  art::Ptr<recob::Track> p(handle, i);
3525  if (&*p == &track) {
3526  std::vector<art::Ptr<recob::SpacePoint>> spts = fmsp.at(i);
3527  DrawSpacePointOrtho(spts, color, proj, msize, view);
3528  }
3529  }
3530  }
3531  }
3532  }
3533  if (recoOpt->fDrawTrackTrajectoryPoints) {
3534 
3535  // Draw trajectory points.
3536 
3537  int np = track.NumberTrajectoryPoints();
3538  int vp = track.CountValidPoints();
3539 
3540  // Make and fill a polymarker.
3541 
3542  TPolyMarker& pm =
3543  view->AddPolyMarker(vp, evd::kColor[color % evd::kNCOLS], kFullCircle, msize);
3544  TPolyLine& pl = view->AddPolyLine(vp, evd::kColor[color % evd::kNCOLS], 2, 0);
3545  for (int p = 0; p < np; ++p) {
3546  if (track.HasValidPoint(p) == 0) continue;
3547  const auto& pos = track.LocationAtPoint(p);
3548  switch (proj) {
3549  case evd::kXY:
3550  pm.SetPoint(p, pos.X(), pos.Y());
3551  pl.SetPoint(p, pos.X(), pos.Y());
3552  break;
3553  case evd::kXZ:
3554  pm.SetPoint(p, pos.Z(), pos.X());
3555  pl.SetPoint(p, pos.Z(), pos.X());
3556  break;
3557  case evd::kYZ:
3558  pm.SetPoint(p, pos.Z(), pos.Y());
3559  pl.SetPoint(p, pos.Z(), pos.Y());
3560  break;
3561  default:
3562  throw cet::exception("RecoBaseDrawer")
3563  << __func__ << ": unknown projection #" << ((int)proj) << "\n";
3564  } // switch
3565  } // p
3566  // BB: draw the track ID at the end of the track
3567  if (recoOpt->fDrawTracks > 1) {
3568  int tid =
3569  track.ID() &
3570  65535; //this is a hack for PMA track id which uses the 16th bit to identify shower-like track.
3571  std::string s = std::to_string(tid);
3572  char const* txt = s.c_str();
3573  double x = track.End().X();
3574  double y = track.End().Y();
3575  double z = track.End().Z();
3576  if (proj == evd::kXY) {
3577  TText& trkID = view->AddText(x, y, txt);
3578  trkID.SetTextColor(evd::kColor[tid % evd::kNCOLS]);
3579  trkID.SetTextSize(0.03);
3580  }
3581  else if (proj == evd::kXZ) {
3582  TText& trkID = view->AddText(z, x, txt);
3583  trkID.SetTextColor(evd::kColor[tid % evd::kNCOLS]);
3584  trkID.SetTextSize(0.03);
3585  }
3586  else if (proj == evd::kYZ) {
3587  TText& trkID = view->AddText(z, y, txt);
3588  trkID.SetTextColor(evd::kColor[tid % evd::kNCOLS]);
3589  trkID.SetTextSize(0.03);
3590  } // proj
3591  } // recoOpt->fDrawTracks > 1
3592  }
3593 
3594  return;
3595  }
3596 
3597  //......................................................................
3599  int color,
3601  double msize,
3602  evdb::View2D* view)
3603  {
3604  // Use brute force to find the module label and index of this
3605  // shower, so that we can find associated space points and draw
3606  // them.
3607 
3609  //std::vector<art::Handle<std::vector<recob::Shower>>> handles;
3610  //evt->getManyByType(handles);
3611  auto handles = evt->getMany<std::vector<recob::Shower>>();
3612  for (auto ih : handles) {
3613  const art::Handle<std::vector<recob::Shower>> handle = ih;
3614  if (handle.isValid()) {
3615  const std::string& which = handle.provenance()->moduleLabel();
3616  art::FindManyP<recob::SpacePoint> fmsp(handle, *evt, which);
3617  if (!fmsp.isValid()) continue;
3618  int n = handle->size();
3619  for (int i = 0; i < n; ++i) {
3620  art::Ptr<recob::Shower> p(handle, i);
3621  if (&*p == &shower) {
3622  switch (proj) {
3623  case evd::kXY:
3624  view->AddMarker(p->ShowerStart().X(),
3625  p->ShowerStart().Y(),
3626  evd::kColor2[color % evd::kNCOLS],
3627  5,
3628  2.0);
3629  break;
3630  case evd::kXZ:
3631  view->AddMarker(p->ShowerStart().Z(),
3632  p->ShowerStart().X(),
3633  evd::kColor2[color % evd::kNCOLS],
3634  5,
3635  2.0);
3636  break;
3637  case evd::kYZ:
3638  view->AddMarker(p->ShowerStart().Z(),
3639  p->ShowerStart().Y(),
3640  evd::kColor2[color % evd::kNCOLS],
3641  5,
3642  2.0);
3643  break;
3644  default:
3645  throw cet::exception("RecoBaseDrawer")
3646  << __func__ << ": unknown projection #" << ((int)proj) << "\n";
3647  } // switch
3648 
3649  if (fmsp.isValid()) {
3650  std::vector<art::Ptr<recob::SpacePoint>> spts = fmsp.at(i);
3651  DrawSpacePointOrtho(spts, color, proj, msize, view, 1);
3652  }
3653  }
3654  }
3655  }
3656  }
3657 
3658  return;
3659  }
3660 
3661  //......................................................................
3663  const art::InputTag& which,
3665  {
3666  wires.clear();
3667 
3670 
3671  try {
3672  evt.getByLabel(which, wcol);
3673 
3674  for (unsigned int i = 0; i < wcol->size(); ++i) {
3675  art::Ptr<recob::Wire> w(wcol, i);
3676  temp.push_back(w);
3677  }
3678  temp.swap(wires);
3679  }
3680  catch (cet::exception& e) {
3681  writeErrMsg("GetWires", e);
3682  }
3683 
3684  return wires.size();
3685  }
3686 
3687  //......................................................................
3689  const art::InputTag& which,
3690  std::vector<const recob::Hit*>& hits,
3691  unsigned int plane)
3692  {
3694  auto const& wireReadoutGeom = getWireReadoutGeom();
3695 
3696  hits.clear();
3697 
3698  std::vector<const recob::Hit*> temp;
3699 
3700  try {
3701  evt.getView(which, temp);
3702  for (const auto& hit : temp) {
3703  // Note that the WireID in the hit object is useless for those detectors where a channel can correspond to
3704  // more than one plane/wire. So our plan is to recover the list of wire IDs from the channel number and
3705  // loop over those (if there are any)
3706  const std::vector<geo::WireID>& wireIDs = wireReadoutGeom.ChannelToWire(hit->Channel());
3707 
3708  // Loop to find match
3709  for (const auto& wireID : wireIDs) {
3710  if (wireID.Plane == plane && wireID.TPC == rawOpt->fTPC &&
3711  wireID.Cryostat == rawOpt->fCryostat)
3712  hits.push_back(hit);
3713  }
3714  }
3715  }
3716  catch (cet::exception& e) {
3717  writeErrMsg("GetHits", e);
3718  }
3719 
3720  return hits.size();
3721  }
3722 
3723  //......................................................................
3725  const art::InputTag& which,
3727  {
3728  slices.clear();
3730 
3732 
3733  try {
3734  evt.getByLabel(which, slcCol);
3735  temp.reserve(slcCol->size());
3736  for (unsigned int i = 0; i < slcCol->size(); ++i) {
3737  art::Ptr<recob::Slice> slc(slcCol, i);
3738  temp.push_back(slc);
3739  }
3740  temp.swap(slices);
3741  }
3742  catch (cet::exception& e) {
3743  writeErrMsg("GetSlices", e);
3744  }
3745 
3746  return slices.size();
3747  }
3748 
3749  //......................................................................
3751  const art::InputTag& which,
3753  {
3754  clust.clear();
3756 
3758 
3759  try {
3760  evt.getByLabel(which, clcol);
3761  temp.reserve(clcol->size());
3762  for (unsigned int i = 0; i < clcol->size(); ++i) {
3763  art::Ptr<recob::Cluster> cl(clcol, i);
3764  temp.push_back(cl);
3765  }
3766  temp.swap(clust);
3767  }
3768  catch (cet::exception& e) {
3769  writeErrMsg("GetClusters", e);
3770  }
3771 
3772  return clust.size();
3773  }
3774 
3775  //......................................................................
3777  const art::InputTag& which,
3779  {
3780  clust.clear();
3782 
3784 
3785  try {
3786  evt.getByLabel(which, clcol);
3787  for (unsigned int i = 0; i < clcol->size(); ++i) {
3788  art::Ptr<recob::PFParticle> cl(clcol, i);
3789  temp.push_back(cl);
3790  }
3791  temp.swap(clust);
3792  }
3793  catch (cet::exception& e) {
3794  writeErrMsg("GetPFParticles", e);
3795  }
3796 
3797  return clust.size();
3798  }
3799 
3800  //......................................................................
3802  const art::InputTag& which,
3804  {
3805  ep2d.clear();
3807 
3809 
3810  try {
3811  evt.getByLabel(which, epcol);
3812  for (unsigned int i = 0; i < epcol->size(); ++i) {
3813  art::Ptr<recob::EndPoint2D> ep(epcol, i);
3814  temp.push_back(ep);
3815  }
3816  temp.swap(ep2d);
3817  }
3818  catch (cet::exception& e) {
3819  writeErrMsg("GetEndPoint2D", e);
3820  }
3821 
3822  return ep2d.size();
3823  }
3824 
3825  //......................................................................
3826 
3828  const art::InputTag& which,
3829  art::PtrVector<recob::OpFlash>& opflashes)
3830  {
3831  opflashes.clear();
3833 
3835 
3836  try {
3837  evt.getByLabel(which, opflashcol);
3838  for (unsigned int i = 0; i < opflashcol->size(); ++i) {
3839  art::Ptr<recob::OpFlash> opf(opflashcol, i);
3840  temp.push_back(opf);
3841  }
3842  temp.swap(opflashes);
3843  }
3844  catch (cet::exception& e) {
3845  writeErrMsg("GetOpFlashes", e);
3846  }
3847 
3848  return opflashes.size();
3849  }
3850 
3851  //......................................................................
3852 
3854  const art::InputTag& which,
3856  {
3857  seeds.clear();
3859 
3861 
3862  try {
3863  evt.getByLabel(which, seedcol);
3864  for (unsigned int i = 0; i < seedcol->size(); ++i) {
3865  art::Ptr<recob::Seed> sd(seedcol, i);
3866  temp.push_back(sd);
3867  }
3868  temp.swap(seeds);
3869  }
3870  catch (cet::exception& e) {
3871  writeErrMsg("GetSeeds", e);
3872  }
3873 
3874  return seeds.size();
3875  }
3876 
3877  //......................................................................
3879  const art::InputTag& which,
3881  {
3882  spts.clear();
3884  if (evt.getByLabel(which, spcol)) art::fill_ptr_vector(spts, spcol);
3885 
3886  return spts.size();
3887  }
3888 
3889  //......................................................................
3891  const art::InputTag& which,
3893  {
3894  edges.clear();
3895 
3897 
3898  evt.getByLabel(which, edgeCol);
3899 
3900  for (unsigned int i = 0; i < edgeCol->size(); ++i)
3901  edges.emplace_back(edgeCol, i);
3902 
3903  return edges.size();
3904  }
3905 
3906  //......................................................................
3908  const art::InputTag& which,
3910  {
3911  try {
3912  evt.getView(which, track);
3913  }
3914  catch (cet::exception& e) {
3915  writeErrMsg("GetTracks", e);
3916  }
3917 
3918  return track.vals().size();
3919  }
3920 
3921  //......................................................................
3923  const art::InputTag& which,
3925  {
3926  try {
3927  evt.getView(which, shower);
3928  }
3929  catch (cet::exception& e) {
3930  writeErrMsg("GetShowers", e);
3931  }
3932 
3933  return shower.vals().size();
3934  }
3935 
3936  //......................................................................
3938  const art::InputTag& which,
3940  {
3941  vertex.clear();
3943 
3945 
3946  try {
3947  evt.getByLabel(which, vcol);
3948  for (size_t i = 0; i < vcol->size(); ++i) {
3949  art::Ptr<recob::Vertex> v(vcol, i);
3950  temp.push_back(v);
3951  }
3952  temp.swap(vertex);
3953  }
3954  catch (cet::exception& e) {
3955  writeErrMsg("GetVertices", e);
3956  }
3957 
3958  return vertex.size();
3959  }
3960 
3961  //......................................................................
3963  const art::InputTag& which,
3965  {
3966  event.clear();
3968 
3970 
3971  try {
3972  evt.getByLabel(which, ecol);
3973  for (size_t i = 0; i < ecol->size(); ++i) {
3974  art::Ptr<recob::Event> e(ecol, i);
3975  temp.push_back(e);
3976  }
3977  temp.swap(event);
3978  }
3979  catch (cet::exception& e) {
3980  writeErrMsg("GetEvents", e);
3981  }
3982 
3983  return event.size();
3984  }
3985 
3986  //......................................................................
3988  const art::InputTag& which,
3989  unsigned int cryostat,
3990  unsigned int tpc,
3991  unsigned int plane)
3992  {
3993  std::vector<const recob::Hit*> temp;
3994  int NumberOfHitsBeforeThisPlane = 0;
3995  evt.getView(
3996  which,
3997  temp); //temp.size() = total number of hits for this event (number of all hits in all Cryostats, TPC's, planes and wires)
3998  for (size_t t = 0; t < temp.size(); ++t) {
3999  if (temp[t]->WireID().Cryostat == cryostat && temp[t]->WireID().TPC == tpc &&
4000  temp[t]->WireID().Plane == plane)
4001  break;
4002  NumberOfHitsBeforeThisPlane++;
4003  }
4004  return NumberOfHitsBeforeThisPlane;
4005  }
4006 
4007  //......................................................................
4009  unsigned int plane,
4010  unsigned int wire,
4011  TH1F* histo)
4012  {
4015  auto const& wireReadoutGeom = getWireReadoutGeom();
4016 
4017  float minSig(std::numeric_limits<float>::max());
4018  float maxSig(std::numeric_limits<float>::lowest());
4019  bool setLimits(false);
4020 
4021  // Check if we're supposed to draw raw hits at all
4022  if (rawOpt->fDrawRawDataOrCalibWires == 0) return;
4023 
4024  for (size_t imod = 0; imod < recoOpt->fWireLabels.size(); ++imod) {
4025  art::InputTag const which = recoOpt->fWireLabels[imod];
4026 
4028  GetWires(evt, which, wires);
4029 
4030  for (size_t i = 0; i < wires.size(); ++i) {
4031 
4032  std::vector<geo::WireID> wireids = wireReadoutGeom.ChannelToWire(wires[i]->Channel());
4033 
4034  bool goodWID = false;
4035  for (auto const& wid : wireids) {
4036  // check for correct plane, wire and tpc
4037  if (wid.Plane == plane && wid.Wire == wire && wid.TPC == rawOpt->fTPC &&
4038  wid.Cryostat == rawOpt->fCryostat)
4039  goodWID = true;
4040  }
4041  if (!goodWID) continue;
4042 
4043  std::vector<float> wirSig = wires[i]->Signal();
4044  for (unsigned int ii = 0; ii < wirSig.size(); ++ii) {
4045  minSig = std::min(minSig, wirSig[ii]);
4046  maxSig = std::max(maxSig, wirSig[ii]);
4047  }
4048 
4049  setLimits = true;
4050  } //end loop over wires
4051  } //end loop over wire modules
4052 
4053  if (setLimits) {
4054  histo->SetMaximum(1.2 * maxSig);
4055  histo->SetMinimum(1.2 * minSig);
4056  }
4057 
4058  return;
4059  }
4060 
4061  //......................................................................
4062  void RecoBaseDrawer::FillQHisto(const art::Event& evt, unsigned int plane, TH1F* histo)
4063  {
4066  auto const& wireReadoutGeom = getWireReadoutGeom();
4067 
4068  // Check if we're supposed to draw raw hits at all
4069  if (rawOpt->fDrawRawDataOrCalibWires == 0) return;
4070 
4071  for (size_t imod = 0; imod < recoOpt->fWireLabels.size(); ++imod) {
4072  art::InputTag const which = recoOpt->fWireLabels[imod];
4073 
4075  GetWires(evt, which, wires);
4076 
4077  for (unsigned int i = 0; i < wires.size(); ++i) {
4078 
4079  std::vector<geo::WireID> wireids = wireReadoutGeom.ChannelToWire(wires[i]->Channel());
4080 
4081  bool goodWID = false;
4082  for (auto const& wid : wireids) {
4083  // check for correct plane, wire and tpc
4084  if (wid.Plane == plane && wid.TPC == rawOpt->fTPC && wid.Cryostat == rawOpt->fCryostat)
4085  goodWID = true;
4086  }
4087  if (!goodWID) continue;
4088  std::vector<float> wirSig = wires[i]->Signal();
4089  for (unsigned int ii = 0; ii < wirSig.size(); ++ii)
4090  histo->Fill(wirSig[ii]);
4091 
4092  } //end loop over raw hits
4093  } //end loop over Wire modules
4094 
4095  return;
4096  }
4097 
4098  //......................................................................
4100  unsigned int plane,
4101  unsigned int wire,
4102  TH1F* histo,
4103  std::vector<double>& htau1,
4104  std::vector<double>& htau2,
4105  std::vector<double>& hitamplitudes,
4106  std::vector<double>& hpeaktimes,
4107  std::vector<int>& hstartT,
4108  std::vector<int>& hendT,
4109  std::vector<int>& hNMultiHit,
4110  std::vector<int>& hLocalHitIndex)
4111  {
4114  auto const& wireReadoutGeom = getWireReadoutGeom();
4115 
4116  // Check if we're supposed to draw raw hits at all
4117  if (rawOpt->fDrawRawDataOrCalibWires == 0) return;
4118 
4119  for (size_t imod = 0; imod < recoOpt->fWireLabels.size(); ++imod) {
4120  art::InputTag const which = recoOpt->fWireLabels[imod];
4121 
4123  GetWires(evt, which, wires);
4124 
4125  for (size_t i = 0; i < wires.size(); ++i) {
4126 
4127  std::vector<geo::WireID> wireids = wireReadoutGeom.ChannelToWire(wires[i]->Channel());
4128 
4129  bool goodWID = false;
4130  for (auto const& wid : wireids) {
4131  if (wid.Plane == plane && wid.Wire == wire && wid.TPC == rawOpt->fTPC &&
4132  wid.Cryostat == rawOpt->fCryostat)
4133  goodWID = true;
4134  }
4135 
4136  if (!goodWID) continue;
4137 
4138  std::vector<float> wirSig = wires[i]->Signal();
4139  for (unsigned int ii = 0; ii < wirSig.size(); ++ii)
4140  histo->Fill(1. * ii, wirSig[ii]);
4141  break;
4142  } //end loop over wires
4143  } //end loop over wire modules
4144 
4145  for (size_t imod = 0; imod < recoOpt->fHitLabels.size(); ++imod) {
4146  art::InputTag const which = recoOpt->fHitLabels[imod];
4147 
4148  std::vector<const recob::Hit*> hits;
4149  GetHits(evt, which, hits, plane);
4150 
4151  auto hitResults = anab::FVectorReader<recob::Hit, 4>::create(evt, "dprawhit");
4152  const auto& fitParams = hitResults->vectors();
4153 
4154  int FitParamsOffset = CountHits(evt, which, rawOpt->fCryostat, rawOpt->fTPC, plane);
4155 
4156  for (size_t i = 0; i < hits.size(); ++i) {
4157  // check for correct wire. Plane, cryostat and tpc were checked in GetHits
4158  if (hits[i]->WireID().Wire != wire) continue;
4159 
4160  hpeaktimes.push_back(fitParams[FitParamsOffset + i][0]);
4161  htau1.push_back(fitParams[FitParamsOffset + i][1]);
4162  htau2.push_back(fitParams[FitParamsOffset + i][2]);
4163  hitamplitudes.push_back(fitParams[FitParamsOffset + i][3]);
4164  hstartT.push_back(hits[i]->StartTick());
4165  hendT.push_back(hits[i]->EndTick());
4166  hNMultiHit.push_back(hits[i]->Multiplicity());
4167  hLocalHitIndex.push_back(hits[i]->LocalIndex());
4168  } //end loop over reco hits
4169  } //end loop over HitFinding modules
4170  }
4171 
4172 } // namespace evd
Float_t x
Definition: compare.C:6
ISpacePointDrawerPtr fSpacePointDrawer
void SpacePointOrtho(const art::Event &evt, evd::OrthoProj_t proj, double msize, evdb::View2D *view)
TRandom r
Definition: spectrum.C:23
void XYZ(double *xyz) const
Legacy method to access vertex position, preserved to avoid breaking code. Please try to use Vertex::...
Definition: Vertex.cxx:34
intermediate_table::iterator iterator
void DrawShowerOrtho(const recob::Shower &shower, int color, evd::OrthoProj_t proj, double msize, evdb::View2D *view)
void SpacePoint3D(const art::Event &evt, evdb::View3D *view)
void reserve(size_type n)
Definition: PtrVector.h:337
int GetTracks(const art::Event &evt, const art::InputTag &which, art::View< recob::Track > &track)
std::vector< double > fRawCharge
Sum of Raw Charge.
const std::vector< size_t > & Daughters() const
Returns the collection of daughter particles.
Definition: PFParticle.h:110
fhicl::ParameterSet fSpacePointDrawerParams
FHICL parameters for SpacePoint drawing.
void FillTQHisto(const art::Event &evt, unsigned int plane, unsigned int wire, TH1F *histo)
const TVector3 & ShowerStart() const
Definition: Shower.h:197
int fScaleDigitsByCharge
scale the size of the digit by the charge
const art::Event * GetEvent() const
Definition: EventHolder.cxx:45
void PFParticleOrtho(const art::Event &evt, evd::OrthoProj_t proj, double msize, evdb::View2D *view)
std::vector< art::InputTag > fEndPoint2DLabels
module labels that produced end point 2d objects
An object to define a "edge" which is used to connect space points in a triangulation algorithm...
unsigned int fTPC
TPC number to draw, typically set by TWQProjectionView.
void DrawProng2D(detinfo::DetectorPropertiesData const &detProp, std::vector< const recob::Hit * > &hits, evdb::View2D *view, unsigned int plane, TVector3 const &startPos, TVector3 const &startDir, int id, float cscore=-5)
int NumDaughters() const
Returns the number of daughter particles flowing from this one.
Definition: PFParticle.h:85
std::vector< art::InputTag > fTrkVtxCosmicLabels
module labels that tagged track as CR (Track/Vertex module)
ISpacePointDrawerPtr fAllSpacePointDrawer
std::vector< art::InputTag > fOpFlashLabels
module labels that produced events
Encapsulate the construction of a single cyostat .
size_t Self() const
Returns the index of this particle.
Definition: PFParticle.h:88
Float_t y1[n_points_granero]
Definition: compare.C:5
Offers proxy::Tracks and proxy::Track class for recob::Track access.
bool has_length() const
Returns whether the shower has a valid length.
Definition: Shower.h:252
TPolyLine & AddPolyLine(int n, int c, int w, int s)
Definition: View2D.cxx:210
WireID suggestedWireID() const
Returns a better wire ID.
Definition: Exceptions.h:85
double Length() const
Definition: Shower.h:227
void Prong3D(const art::Event &evt, evdb::View3D *view)
float SpacePointChiSq(const std::vector< art::Ptr< recob::Hit >> &) const
std::vector< art::InputTag > fTrackLabels
module labels that produced tracks
void DrawPFParticle3D(const art::Ptr< recob::PFParticle > &pfPart, const art::PtrVector< recob::PFParticle > &pfParticleVec, const std::vector< art::Ptr< recob::SpacePoint >> &spacePointVec, const art::FindManyP< recob::Edge > &edgeAssnsVec, const art::FindManyP< recob::SpacePoint > &spacePointAssnsVec, const art::FindManyP< recob::SpacePoint > &edgeSPAssnVec, const art::FindManyP< recob::Hit > &spHitAssnVec, const art::FindMany< recob::Track > &trackAssnVec, const art::FindMany< recob::PCAxis > &pcAxisAssnVec, const art::FindMany< anab::CosmicTag > &cosmicTagAssnVec, int depth, evdb::View3D *view)
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
void swap(PtrVector &other)
Definition: PtrVector.h:518
int GetSpacePoints(const art::Event &evt, const art::InputTag &which, std::vector< art::Ptr< recob::SpacePoint >> &spts)
int fDrawRawDataOrCalibWires
0 for raw
double GetXTicksOffset(int p, int t, int c) const
Float_t x1[n_points_granero]
Definition: compare.C:5
void SeedOrtho(const art::Event &evt, evd::OrthoProj_t proj, evdb::View2D *view)
TLine & AddLine(double x1, double y1, double x2, double y2)
Definition: View2D.cxx:187
Declaration of signal hit object.
std::vector< art::InputTag > fTrkVtxTrackLabels
module labels that produced tracks (Track/Vertex module)
Float_t y
Definition: compare.C:6
int fColorSpacePointsByChisq
Generate space point colors by chisquare?
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
Float_t Y
Definition: plot.C:37
The data type to uniquely identify a Plane.
Definition: geo_types.h:364
Geometry information for a single TPC.
Definition: TPCGeo.h:33
void Vertex3D(const art::Event &evt, evdb::View3D *view)
bool HasValidPoint(size_t i) const
Various functions related to the presence and the number of (valid) points.
Definition: Track.h:145
void Event3D(const art::Event &evt, evdb::View3D *view)
static std::unique_ptr< FVectorReader > create(const art::Event &evt, const art::InputTag &tag)
Definition: MVAReader.h:28
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.
Vector_t VertexDirection() const
Access to track direction at different points.
Definition: Track.h:166
void ProngOrtho(const art::Event &evt, evd::OrthoProj_t proj, double msize, evdb::View2D *view)
int GetClusters(const art::Event &evt, const art::InputTag &which, art::PtrVector< recob::Cluster > &clust)
Plane(const Point_t &planePos, const Vector_t &planeDir)
Constructor from reference position on the plane and direction orthogonal to the plane.
Definition: TrackingPlane.h:60
cout<< "Opened file "<< fin<< " ixs= "<< ixs<< endl;if(ixs==0) hhh=(TH1F *) fff-> Get("h1")
Definition: AddMC.C:8
void DrawShower3D(const recob::Shower &shower, int color, evdb::View3D *view)
A collection of drawable 2-D objects.
WireID_t Wire
Index of the wire within its plane.
Definition: geo_types.h:430
static const int kNCOLS
Definition: eventdisplay.h:10
intermediate_table::const_iterator const_iterator
int GetColor(double x) const
Definition: ColorScale.cxx:126
void DrawSpacePointOrtho(std::vector< art::Ptr< recob::SpacePoint >> &spts, int color, evd::OrthoProj_t proj, double msize, evdb::View2D *view, int mode=0)
0: track, 1: shower
void Edge3D(const art::Event &evt, evdb::View3D *view)
OrthoProj_t
Definition: OrthoProj.h:12
void fill(PtrVector< T > &pv) const
Definition: View.h:145
int GetEvents(const art::Event &evt, const art::InputTag &which, art::PtrVector< recob::Event > &event)
double fFlashTMin
Minimal time for a flash to be displayed.
void Prong2D(const art::Event &evt, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, evdb::View2D *view, unsigned int plane)
Singleton to hold the current art::Event for the event display.
float & CosmicScore()
Definition: CosmicTag.h:54
std::vector< art::InputTag > fExtremePointLabels
module labels that produced Extreme Points
std::vector< art::InputTag > fCosmicTagLabels
module labels that produced cosmic tags
std::vector< double > fConvertedCharge
Sum of Charge Converted using Birks&#39; formula.
bool has_open_angle() const
Returns whether the shower has a valid opening angle.
Definition: Shower.h:248
Float_t y2[n_points_geant4]
Definition: compare.C:26
double fFlashTMax
Maximum time for a flash to be displayed.
double Length() const
Length is associated with z coordinate [cm].
Definition: TPCGeo.h:110
void Slice2D(const art::Event &evt, detinfo::DetectorPropertiesData const &detProp, evdb::View2D *view, unsigned int plane)
void Cluster2D(const art::Event &evt, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, evdb::View2D *view, unsigned int plane)
void DrawTrackVertexAssns2D(const art::Event &evt, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, evdb::View2D *view, unsigned int plane)
Float_t Z
Definition: plot.C:37
bool isValid() const noexcept
Definition: Handle.h:203
auto & vals() noexcept
Definition: View.h:68
The color scales used by the event display.
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
unsigned int CountValidPoints() const
Various functions related to the presence and the number of (valid) points.
Definition: Track.h:146
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
TPolyLine3D & AddPolyLine3D(int n, int c, int w, int s)
Definition: View3D.cxx:105
TBox & AddBox(double x1, double y1, double x2, double y2)
Definition: View2D.cxx:263
void Seed3D(const art::Event &evt, evdb::View3D *view)
int CountHits(const art::Event &evt, const art::InputTag &which, unsigned int cryostat, unsigned int tpc, unsigned int plane)
Point_t GetCenter() const
Returns the center of the TPC volume in world coordinates [cm].
Definition: TPCGeo.h:132
Collection of exceptions for Geometry system.
std::vector< art::InputTag > fWireLabels
module labels that produced wires
void hits()
Definition: readHits.C:15
TPCID FindTPCAtPosition(Point_t const &point) const
Returns the ID of the TPC at specified location.
void Seed2D(const art::Event &evt, detinfo::DetectorPropertiesData const &detProp, evdb::View2D *view, unsigned int plane)
int GetEndPoint2D(const art::Event &evt, const art::InputTag &which, art::PtrVector< recob::EndPoint2D > &ep2d)
const std::vector< double > & dEdx() const
Definition: Shower.h:235
LArSoft includes.
IDparameter< geo::WireID > WireID
Member type of validated geo::WireID parameter.
void push_back(Ptr< U > const &p)
Definition: PtrVector.h:435
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
void FillTQHistoDP(const art::Event &evt, unsigned int plane, unsigned int wire, TH1F *histo, std::vector< double > &htau1, std::vector< double > &htau2, std::vector< double > &hitamplitudes, std::vector< double > &hpeaktimes, std::vector< int > &hstartT, std::vector< int > &hendT, std::vector< int > &hNMultiHit, std::vector< int > &hLocalHitIndex)
Float_t radius
Definition: plot.C:23
unsigned int fCryostat
Cryostat number to draw, typically set by TWQProjectionView.
enum geo::_plane_sigtype SigType_t
Enumerate the possible plane projections.
Provenance const * provenance() const
Definition: Handle.h:217
static EventHolder * Instance()
Definition: EventHolder.cxx:15
void PFParticle3D(const art::Event &evt, evdb::View3D *view)
std::vector< art::InputTag > fPFParticleLabels
module labels that produced PFParticles
std::vector< art::InputTag > fVertexLabels
module labels that produced vertices
key_type key() const noexcept
Definition: Ptr.h:166
void Draw2DSlopeEndPoints(double xStart, double yStart, double xEnd, double yEnd, double slope, int color, evdb::View2D *view)
TPolyMarker & AddPolyMarker(int n, int c, int st, double sz)
Definition: View2D.cxx:157
double OpenAngle() const
Definition: Shower.h:231
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Definition: PlaneGeo.h:67
Point_t const & Vertex() const
Access to track position at different points.
Definition: Track.h:158
const evdb::ColorScale & CalQ(geo::SigType_t st) const
std::vector< art::InputTag > fEdgeLabels
module labels that produced Edge objects
TMarker * pt
Definition: egs.C:25
TText & AddText(double x, double y, const char *text)
Definition: View2D.cxx:286
double fMinSignal
minimum ADC count to display a time bin
double fTicks
number of TDC ticks to display, ie # fTicks past fStartTick
int Hit2D(const art::Event &evt, detinfo::DetectorPropertiesData const &detProp, evdb::View2D *view, unsigned int plane)
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:73
double ConvertXToTicks(double X, int p, int t, int c) const
int GetSlices(const art::Event &evt, const art::InputTag &which, art::PtrVector< recob::Slice > &slices)
void Slice3D(const art::Event &evt, evdb::View3D *view)
void DrawTrack2D(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::vector< const recob::Hit * > &hits, evdb::View2D *view, unsigned int plane, const recob::Track *track, int color, int lineWidth)
std::vector< int > fWireMax
highest wire in interesting region for each plane
int GetHits(const art::Event &evt, const art::InputTag &which, std::vector< const recob::Hit * > &hits, unsigned int plane)
Definition: fwd.h:46
Point_t toPoint(Point const &p)
Convert the specified point into a geo::Point_t.
std::vector< std::array< double, 3 > > Circle3D(const TVector3 &pos, const TVector3 &axisDir, const double &radius)
int GetWires(const art::Event &evt, const art::InputTag &which, art::PtrVector< recob::Wire > &wires)
fhicl::ParameterSet fAllSpacePointDrawerParams
FHICL parameters for SpacePoint drawing.
const Double32_t * XYZ() const
Definition: SpacePoint.h:78
std::vector< art::InputTag > fSliceLabels
module labels that produced slices
const TVector3 & Direction() const
Definition: Shower.h:188
int GetOpFlashes(const art::Event &evt, const art::InputTag &which, art::PtrVector< recob::OpFlash > &opflash)
int GetSeeds(const art::Event &evt, const art::InputTag &which, art::PtrVector< recob::Seed > &seed)
int GetShowers(const art::Event &evt, const art::InputTag &which, art::View< recob::Shower > &shower)
reference at(size_type n)
Definition: PtrVector.h:359
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
double fFlashMinPE
Minimal PE for a flash to be displayed.
std::vector< int > fWireMin
lowest wire in interesting region for each plane
The data type to uniquely identify a TPC.
Definition: geo_types.h:306
std::vector< art::InputTag > fSeedLabels
module labels that produced events
Declaration of cluster object.
Class to aid in the rendering of RecoBase objects.
static const int kColor[kNCOLS]
Definition: eventdisplay.h:11
bool empty() const
Definition: PtrVector.h:330
void GetChargeSum(int plane, double &charge, double &convcharge)
size_type size() const
Definition: PtrVector.h:302
std::vector< TCSlice > slices
Definition: DataStructs.cxx:13
Detector simulation of raw signals on wires.
Encapsulate the geometry of a wire .
double ConvertTicksToX(double ticks, int p, int t, int c) const
std::vector< art::InputTag > fSpacePointLabels
module labels that produced space points
std::size_t getView(std::string const &moduleLabel, std::string const &productInstanceName, std::string const &processName, std::vector< ELEMENT const * > &result) const
std::size_t color(std::string const &procname)
std::vector< TrajPoint > seeds
Definition: DataStructs.cxx:14
void DrawTrack3D(const recob::Track &track, evdb::View3D *view, int color, int marker=1, float size=2.)
Color
Definition: test07.cc:35
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
int ID() const
Definition: Track.h:244
Place to keep constants for event display.
ID_t ID() const
Definition: SpacePoint.h:74
int fTicksPerPoint
number of ticks to include in one point
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
Encapsulate the construction of a single detector plane .
auto isValid() const noexcept
Definition: View.h:52
bool fSeeBadChannels
Allow "bad" channels to be viewed.
Contains all timing reference information for the detector.
Provides recob::Track data product.
TDirectory * dir
Definition: macro.C:5
#define MF_LOG_VERBATIM(category)
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
void FillQHisto(const art::Event &evt, unsigned int plane, TH1F *histo)
double BirksCorrection(double dQdX) const
dQ/dX in electrons/cm, returns dE/dX in MeV/cm.
int ID() const
Return vertex id.
Definition: Vertex.h:101
int GetPFParticles(const art::Event &evt, const art::InputTag &which, art::PtrVector< recob::PFParticle > &pfpart)
Float_t proj
Definition: plot.C:35
void EndPoint2D(const art::Event &evt, evdb::View2D *view, unsigned int plane)
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
void Wire2D(const art::Event &evt, evdb::View2D *view, unsigned int plane)
int fAxisOrientation
0 = TDC values on y-axis, wire number on x-axis, 1 = swapped
void DrawPFParticleOrtho(const art::Ptr< recob::PFParticle > &pfPart, const art::PtrVector< recob::PFParticle > &pfParticleVec, const art::FindMany< recob::SpacePoint > &spacePointAssnsVec, const art::FindMany< recob::PCAxis > &pcAxisAssnVec, int depth, evd::OrthoProj_t proj, evdb::View2D *view)
Exception thrown on invalid wire number.
Definition: Exceptions.h:37
Point_t const & End() const
Access to track position at different points.
Definition: Track.h:159
Declaration of basic channel signal object.
void OpFlash2D(const art::Event &evt, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, evdb::View2D *view, unsigned int plane)
int GetRegionOfInterest(int plane, int &minw, int &maxw, int &mint, int &maxt)
Char_t n[5]
Vector_t DirectionAtPoint(size_t i) const
Access to track direction at different points.
Definition: Track.h:168
void Event2D(const art::Event &evt, evdb::View2D *view, unsigned int plane)
void GetClusterOutlines(std::vector< const recob::Hit * > &hits, std::vector< double > &tpts, std::vector< double > &wpts, unsigned int plane)
A collection of 3D drawable objects.
void OpFlashOrtho(const art::Event &evt, detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, evd::OrthoProj_t proj, evdb::View2D *view)
std::vector< art::InputTag > fHitLabels
module labels that produced hits
std::vector< art::InputTag > fShowerLabels
module labels that produced showers
TCEvent evt
Definition: DataStructs.cxx:8
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
void Vertex2D(const art::Event &evt, detinfo::DetectorPropertiesData const &detProp, evdb::View2D *view, unsigned int plane)
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:306
TPCGeo const & TPC(TPCID const &tpcid=details::tpc_zero) const
Returns the specified TPC.
Definition: GeometryCore.h:448
std::vector< art::InputTag > fTrkVtxFilterLabels
module labels that filtered event (Track/Vertex module)
void DrawTrackOrtho(const recob::Track &track, int color, evd::OrthoProj_t proj, double msize, evdb::View2D *view)
Float_t x2[n_points_geant4]
Definition: compare.C:26
Float_t e
Definition: plot.C:35
T const * get() const
Definition: Ptr.h:138
static const int kColor2[kNCOLS]
Definition: eventdisplay.h:25
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
recob::tracking::Plane Plane
Definition: TrackState.h:17
Float_t X
Definition: plot.C:37
ROOT libraries.
Float_t track
Definition: plot.C:35
TMarker & AddMarker(double x, double y, int c, int st, double sz)
Definition: View2D.cxx:124
void clear()
Definition: PtrVector.h:533
Float_t w
Definition: plot.C:20
Point3DBase_t< PlaneGeoCoordinatesTag > LocalPoint_t
Type of points in the local GDML wire plane frame.
Definition: PlaneGeo.h:94
std::vector< int > fTimeMax
highest time in interesting region for each plane
int ID() const
Definition: Shower.h:183
std::vector< art::InputTag > fClusterLabels
module labels that produced clusters
Definition: fwd.h:26
std::vector< art::InputTag > fEventLabels
module labels that produced events
int GetVertices(const art::Event &evt, const art::InputTag &which, art::PtrVector< recob::Vertex > &vertex)
art framework interface to geometry description
double HalfWidth() const
Width is associated with x coordinate [cm].
Definition: TPCGeo.h:102
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
void VertexOrtho(const art::PtrVector< recob::Vertex > &vertex, evd::OrthoProj_t proj, evdb::View2D *view, int marker)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
int GetEdges(const art::Event &evt, const art::InputTag &which, std::vector< art::Ptr< recob::Edge >> &edges)
Event finding and building.
TPolyMarker3D & AddPolyMarker3D(int n, int c, int st, double sz)
Definition: View3D.cxx:75
Encapsulate the construction of a single detector plane .
The data type to uniquely identify a cryostat.
Definition: geo_types.h:187
std::vector< Handle< PROD > > getMany(SelectorBase const &selector=MatchAllSelector{}) const
std::vector< int > fTimeMin
lowest time in interesting region for each plane
vertex reconstruction