Pandora
Pandora source code navigator
Loading...
Searching...
No Matches
DlVertexingAlgorithm.cc
Go to the documentation of this file.
1
9#include <chrono>
10#include <cmath>
11
12#include <torch/script.h>
13#include <torch/torch.h>
14
19
21
22using namespace pandora;
23using namespace lar_content;
24
25namespace lar_dl_content
26{
27
29 m_trainingMode{false},
30 m_trainingOutputFile{""},
31 m_event{-1},
32 m_pass{1},
33 m_nClasses{0},
34 m_height{256},
35 m_width{256},
36 m_driftStep{0.5f},
37 m_visualise{false},
38 m_writeTree{false},
39 m_rng(static_cast<std::mt19937::result_type>(std::chrono::high_resolution_clock::now().time_since_epoch().count())),
40 m_volumeType{"dune_fd_hd"}
41{
42}
43
45{
46 if (m_writeTree)
47 {
48 try
49 {
50 PANDORA_MONITORING_API(SaveTree(this->GetPandora(), m_rootTreeName, m_rootFileName, "RECREATE"));
51 }
52 catch (StatusCodeException e)
53 {
54 std::cout << "VertexAssessmentAlgorithm: Unable to write to ROOT tree" << std::endl;
55 }
56 }
57}
58
59//-----------------------------------------------------------------------------------------------------------------------------------------
60
62{
64 return this->PrepareTrainingSample();
65 else
66 return this->Infer();
67
68 return STATUS_CODE_SUCCESS;
69}
70
72{
74 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->GetMCToHitsMap(mcToHitsMap));
75 MCParticleList hierarchy;
76 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->CompleteMCHierarchy(mcToHitsMap, hierarchy));
77
78 // Get boundaries for hits and make x dimension common
79 std::map<HitType, float> wireMin, wireMax;
80 float driftMin{std::numeric_limits<float>::max()}, driftMax{-std::numeric_limits<float>::max()};
81 for (const std::string &listname : m_caloHitListNames)
82 {
83 const CaloHitList *pCaloHitList{nullptr};
84 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, listname, pCaloHitList));
85 if (pCaloHitList->empty())
86 continue;
87
88 HitType view{pCaloHitList->front()->GetHitType()};
89 float viewDriftMin{driftMin}, viewDriftMax{driftMax};
90 this->GetHitRegion(*pCaloHitList, viewDriftMin, viewDriftMax, wireMin[view], wireMax[view]);
91 driftMin = std::min(viewDriftMin, driftMin);
92 driftMax = std::max(viewDriftMax, driftMax);
93 }
94 for (const std::string &listname : m_caloHitListNames)
95 {
96 const CaloHitList *pCaloHitList(nullptr);
97 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, listname, pCaloHitList));
98 if (pCaloHitList->empty())
99 continue;
100
101 HitType view{pCaloHitList->front()->GetHitType()};
102 const bool isU{view == TPC_VIEW_U}, isV{view == TPC_VIEW_V}, isW{view == TPC_VIEW_W};
103 if (!(isU || isV || isW))
104 return STATUS_CODE_NOT_ALLOWED;
105
106 CartesianPointVector vertices;
107 for (const MCParticle *mc : hierarchy)
108 {
110 vertices.push_back(mc->GetVertex());
111 }
112 if (vertices.empty())
113 continue;
114 const CartesianVector &vertex{vertices.front()};
115 const std::string trainingFilename{m_trainingOutputFile + "_" + listname + ".csv"};
116 const unsigned long nVertices{1};
117 unsigned long nHits{0};
118 const unsigned int nuance{LArMCParticleHelper::GetNuanceCode(hierarchy.front())};
119
120 // Vertices
122 const double xVtx{vertex.GetX()};
123 double zVtx{0.};
124 if (isW)
125 zVtx = transform->YZtoW(vertex.GetY(), vertex.GetZ());
126 else if (isV)
127 zVtx = transform->YZtoV(vertex.GetY(), vertex.GetZ());
128 else
129 zVtx = transform->YZtoU(vertex.GetY(), vertex.GetZ());
130
131 // Calo hits
132 double xMin{driftMin}, xMax{driftMax}, zMin{wireMin[view]}, zMax{wireMax[view]};
133
134 // Only train on events where the vertex resides within the image - with a small tolerance
135 if (!(xVtx > (xMin - 1.f) && xVtx < (xMax + 1.f) && zVtx > (zMin - 1.f) && zVtx < (zMax + 1.f)))
136 continue;
137
138 LArMvaHelper::MvaFeatureVector featureVector;
139 featureVector.emplace_back(static_cast<double>(nuance));
140 featureVector.emplace_back(static_cast<double>(nVertices));
141 featureVector.emplace_back(xVtx);
142 featureVector.emplace_back(zVtx);
143 // Retain the hit region
144 featureVector.emplace_back(xMin);
145 featureVector.emplace_back(xMax);
146 featureVector.emplace_back(zMin);
147 featureVector.emplace_back(zMax);
148
149 for (const CaloHit *pCaloHit : *pCaloHitList)
150 {
151 const float x{pCaloHit->GetPositionVector().GetX()}, z{pCaloHit->GetPositionVector().GetZ()}, adc{pCaloHit->GetMipEquivalentEnergy()};
152 // If on a refinement pass, drop hits outside the region of interest
153 if (m_pass > 1 && (x < xMin || x > xMax || z < zMin || z > zMax))
154 continue;
155 featureVector.emplace_back(static_cast<double>(x));
156 featureVector.emplace_back(static_cast<double>(z));
157 featureVector.emplace_back(static_cast<double>(adc));
158 ++nHits;
159 }
160 featureVector.insert(featureVector.begin() + 8, static_cast<double>(nHits));
161 // Only write out the feature vector if there were enough hits in the region of interest
162 if (nHits > 10)
163 LArMvaHelper::ProduceTrainingExample(trainingFilename, true, featureVector);
164 }
165
166 return STATUS_CODE_SUCCESS;
167}
168
169//-----------------------------------------------------------------------------------------------------------------------------------------
170
172{
173 if (m_pass == 1)
174 ++m_event;
175
176 std::map<HitType, float> wireMin, wireMax;
177 float driftMin{std::numeric_limits<float>::max()}, driftMax{-std::numeric_limits<float>::max()};
178 for (const std::string &listname : m_caloHitListNames)
179 {
180 const CaloHitList *pCaloHitList{nullptr};
181 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, listname, pCaloHitList));
182 if (pCaloHitList->empty())
183 continue;
184
185 HitType view{pCaloHitList->front()->GetHitType()};
186 float viewDriftMin{driftMin}, viewDriftMax{driftMax};
187 this->GetHitRegion(*pCaloHitList, viewDriftMin, viewDriftMax, wireMin[view], wireMax[view]);
188 driftMin = std::min(viewDriftMin, driftMin);
189 driftMax = std::max(viewDriftMax, driftMax);
190 }
191
192 CartesianPointVector vertexCandidatesU, vertexCandidatesV, vertexCandidatesW;
193 for (const std::string &listName : m_caloHitListNames)
194 {
195 const CaloHitList *pCaloHitList{nullptr};
196 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, listName, pCaloHitList));
197
198 HitType view{pCaloHitList->front()->GetHitType()};
199 const bool isU{view == TPC_VIEW_U}, isV{view == TPC_VIEW_V}, isW{view == TPC_VIEW_W};
200 if (!isU && !isV && !isW)
201 return STATUS_CODE_NOT_ALLOWED;
202
204 PixelVector pixelVector;
205 this->MakeNetworkInputFromHits(*pCaloHitList, view, driftMin, driftMax, wireMin[view], wireMax[view], input, pixelVector);
206
207 // Run the input through the trained model
209 inputs.push_back(input);
211 if (isU)
212 LArDLHelper::Forward(m_modelU, inputs, output);
213 else if (isV)
214 LArDLHelper::Forward(m_modelV, inputs, output);
215 else
216 LArDLHelper::Forward(m_modelW, inputs, output);
217
218 int colOffset{0}, rowOffset{0}, canvasWidth{m_width}, canvasHeight{m_height};
219 this->GetCanvasParameters(output, pixelVector, colOffset, rowOffset, canvasWidth, canvasHeight);
220
221 float **canvas{new float *[canvasHeight]};
222 for (int row = 0; row < canvasHeight; ++row)
223 canvas[row] = new float[canvasWidth]{};
224
225 // we want the maximum value in the num_classes dimension (1) for every pixel
226 auto classes{torch::argmax(output, 1)};
227 // the argmax result is a 1 x height x width tensor where each element is a class id
228 auto classesAccessor{classes.accessor<long, 3>()};
229 const double scaleFactor{std::sqrt(m_height * m_height + m_width * m_width)};
230 std::map<int, bool> haveSeenMap;
231 for (const auto &[row, col] : pixelVector)
232 {
233 const auto cls{classesAccessor[0][row][col]};
234 if (cls > 0 && cls < m_nClasses)
235 {
236 const int inner{static_cast<int>(std::round(std::ceil(scaleFactor * m_thresholds[cls - 1])))};
237 const int outer{static_cast<int>(std::round(std::ceil(scaleFactor * m_thresholds[cls])))};
238 this->DrawRing(canvas, row + rowOffset, col + colOffset, inner, outer, 1.f / (outer * outer - inner * inner));
239 }
240 }
241
242 CartesianPointVector positionVector;
244 canvas, canvasWidth, canvasHeight, colOffset, rowOffset, view, driftMin, driftMax, wireMin[view], wireMax[view], positionVector);
245 if (isU)
246 vertexCandidatesU.emplace_back(positionVector.front());
247 else if (isV)
248 vertexCandidatesV.emplace_back(positionVector.front());
249 else
250 vertexCandidatesW.emplace_back(positionVector.front());
251
252#ifdef MONITORING
253 if (m_visualise)
254 {
255 PANDORA_MONITORING_API(SetEveDisplayParameters(this->GetPandora(), true, DETECTOR_VIEW_XZ, -1.f, 1.f, 1.f));
256 try
257 {
258 float x{0.f}, u{0.f}, v{0.f}, w{0.f};
259 this->GetTrueVertexPosition(x, u, v, w);
260 if (isU)
261 {
262 const CartesianVector trueVertex(x, 0.f, u);
263 PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &trueVertex, "U(true)", BLUE, 3));
264 }
265 else if (isV)
266 {
267 const CartesianVector trueVertex(x, 0.f, v);
268 PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &trueVertex, "V(true)", BLUE, 3));
269 }
270 else if (isW)
271 {
272 const CartesianVector trueVertex(x, 0.f, w);
273 PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &trueVertex, "W(true)", BLUE, 3));
274 }
275 }
276 catch (StatusCodeException &e)
277 {
278 std::cerr << "DlVertexingAlgorithm: Warning. Couldn't find true vertex." << std::endl;
279 }
280 for (const auto &pos : positionVector)
281 {
282 std::string label{isU ? "U" : isV ? "V" : "W"};
283 PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &pos, label, RED, 3));
284 }
285 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
286 }
287#endif
288
289 for (int row = 0; row < canvasHeight; ++row)
290 delete[] canvas[row];
291 delete[] canvas;
292 }
293
294 int nEmptyLists{0};
295 if (vertexCandidatesU.empty())
296 ++nEmptyLists;
297 if (vertexCandidatesV.empty())
298 ++nEmptyLists;
299 if (vertexCandidatesW.empty())
300 ++nEmptyLists;
301 std::vector<VertexTuple> vertexTuples;
302 CartesianPointVector candidates3D;
303 if (nEmptyLists == 0)
304 {
305 vertexTuples.emplace_back(VertexTuple(this->GetPandora(), vertexCandidatesU.front(), vertexCandidatesV.front(), vertexCandidatesW.front()));
306 }
307 else if (nEmptyLists == 1)
308 {
309 if (vertexCandidatesU.empty())
310 { // V and W available
311 vertexTuples.emplace_back(VertexTuple(this->GetPandora(), vertexCandidatesV.front(), vertexCandidatesW.front(), TPC_VIEW_V, TPC_VIEW_W));
312 }
313 else if (vertexCandidatesV.empty())
314 { // U and W available
315 vertexTuples.emplace_back(VertexTuple(this->GetPandora(), vertexCandidatesU.front(), vertexCandidatesW.front(), TPC_VIEW_U, TPC_VIEW_W));
316 }
317 else
318 { // U and V available
319 vertexTuples.emplace_back(VertexTuple(this->GetPandora(), vertexCandidatesU.front(), vertexCandidatesV.front(), TPC_VIEW_U, TPC_VIEW_V));
320 }
321 }
322 else
323 { // Not enough views to reconstruct a 3D vertex
324 std::cout << "Insufficient 2D vertices to reconstruct a 3D vertex" << std::endl;
325 return STATUS_CODE_NOT_FOUND;
326 }
327
328 if (m_visualise)
329 {
330 PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &vertexTuples.front().GetPosition(), "candidate", GREEN, 1));
331 }
332
333 if (!vertexTuples.empty())
334 {
335 const CartesianVector &vertex{vertexTuples.front().GetPosition()};
336 CartesianPointVector vertexCandidates;
337 vertexCandidates.emplace_back(vertex);
338 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->MakeCandidateVertexList(vertexCandidates));
339 }
340 else
341 {
342 std::cout << "Insufficient 2D vertices to reconstruct a 3D vertex" << std::endl;
343 return STATUS_CODE_NOT_FOUND;
344 }
345
346 if (m_visualise)
347 {
348 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
349 }
350
351 return STATUS_CODE_SUCCESS;
352}
353
354//-----------------------------------------------------------------------------------------------------------------------------------------
355
357 const float xMax, const float zMin, const float zMax, LArDLHelper::TorchInput &networkInput, PixelVector &pixelVector) const
358{
359 // ATTN If wire w pitches vary between TPCs, exception will be raised in initialisation of lar pseudolayer plugin
360 const LArTPC *const pTPC(this->GetPandora().GetGeometry()->GetLArTPCMap().begin()->second);
361 const float pitch(view == TPC_VIEW_U ? pTPC->GetWirePitchU() : view == TPC_VIEW_V ? pTPC->GetWirePitchV() : pTPC->GetWirePitchW());
362
363 // Determine the bin edges
364 std::vector<double> xBinEdges(m_width + 1);
365 std::vector<double> zBinEdges(m_height + 1);
366 xBinEdges[0] = xMin - 0.5f * m_driftStep;
367 const double dx = ((xMax + 0.5f * m_driftStep) - xBinEdges[0]) / m_width;
368 for (int i = 1; i < m_width + 1; ++i)
369 xBinEdges[i] = xBinEdges[i - 1] + dx;
370 zBinEdges[0] = zMin - 0.5f * pitch;
371 const double dz = ((zMax + 0.5f * pitch) - zBinEdges[0]) / m_height;
372 for (int i = 1; i < m_height + 1; ++i)
373 zBinEdges[i] = zBinEdges[i - 1] + dz;
374
375 LArDLHelper::InitialiseInput({1, 1, m_height, m_width}, networkInput);
376 auto accessor = networkInput.accessor<float, 4>();
377
378 for (const CaloHit *pCaloHit : caloHits)
379 {
380 const float x{pCaloHit->GetPositionVector().GetX()};
381 const float z{pCaloHit->GetPositionVector().GetZ()};
382 if (m_pass > 1)
383 {
384 if (x < xMin || x > xMax || z < zMin || z > zMax)
385 continue;
386 }
387 const float adc{pCaloHit->GetMipEquivalentEnergy()};
388 const int pixelX{static_cast<int>(std::floor((x - xBinEdges[0]) / dx))};
389 const int pixelZ{static_cast<int>(std::floor((z - zBinEdges[0]) / dz))};
390 accessor[0][0][pixelZ][pixelX] += adc;
391 }
392 for (int row = 0; row < m_height; ++row)
393 {
394 for (int col = 0; col < m_width; ++col)
395 {
396 const float value{accessor[0][0][row][col]};
397 if (value > 0)
398 pixelVector.emplace_back(std::make_pair(row, col));
399 }
400 }
401
402 return STATUS_CODE_SUCCESS;
403}
404
405//-----------------------------------------------------------------------------------------------------------------------------------------
406
407StatusCode DlVertexingAlgorithm::MakeWirePlaneCoordinatesFromCanvas(float **canvas, const int canvasWidth, const int canvasHeight,
408 const int columnOffset, const int rowOffset, const HitType view, const float xMin, const float xMax, const float zMin, const float zMax,
409 CartesianPointVector &positionVector) const
410{
411 // ATTN If wire w pitches vary between TPCs, exception will be raised in initialisation of lar pseudolayer plugin
412 const LArTPC *const pTPC(this->GetPandora().GetGeometry()->GetLArTPCMap().begin()->second);
413 const float pitch(view == TPC_VIEW_U ? pTPC->GetWirePitchU() : view == TPC_VIEW_V ? pTPC->GetWirePitchV() : pTPC->GetWirePitchW());
414
415 const double dx = ((xMax + 0.5f * m_driftStep) - (xMin - 0.5f * m_driftStep)) / m_width;
416 const double dz = ((zMax + 0.5f * pitch) - (zMin - 0.5f * pitch)) / m_height;
417
418 float best{-1.f};
419 int rowBest{0}, colBest{0};
420 for (int row = 0; row < canvasHeight; ++row)
421 for (int col = 0; col < canvasWidth; ++col)
422 if (canvas[row][col] > 0 && canvas[row][col] > best)
423 {
424 best = canvas[row][col];
425 rowBest = row;
426 colBest = col;
427 }
428
429 const float x{static_cast<float>((colBest - columnOffset) * dx + xMin)};
430 const float z{static_cast<float>((rowBest - rowOffset) * dz + zMin)};
431
432 CartesianVector pt(x, 0.f, z);
433 positionVector.emplace_back(pt);
434
435 return STATUS_CODE_SUCCESS;
436}
437
438//-----------------------------------------------------------------------------------------------------------------------------------------
439
441 int &colOffset, int &rowOffset, int &width, int &height) const
442{
443 const double scaleFactor{std::sqrt(m_height * m_height + m_width * m_width)};
444 // output is a 1 x num_classes x height x width tensor
445 // we want the maximum value in the num_classes dimension (1) for every pixel
446 auto classes{torch::argmax(networkOutput, 1)};
447 // the argmax result is a 1 x height x width tensor where each element is a class id
448 auto classesAccessor{classes.accessor<long, 3>()};
449 int colOffsetMin{0}, colOffsetMax{0}, rowOffsetMin{0}, rowOffsetMax{0};
450 for (const auto &[row, col] : pixelVector)
451 {
452 const auto cls{classesAccessor[0][row][col]};
453 const double threshold{m_thresholds[cls]};
454 if (threshold > 0. && threshold < 1.)
455 {
456 const int distance = static_cast<int>(std::round(std::ceil(scaleFactor * threshold)));
457 if ((row - distance) < rowOffsetMin)
458 rowOffsetMin = row - distance;
459 if ((row + distance) > rowOffsetMax)
460 rowOffsetMax = row + distance;
461 if ((col - distance) < colOffsetMin)
462 colOffsetMin = col - distance;
463 if ((col + distance) > colOffsetMax)
464 colOffsetMax = col + distance;
465 }
466 }
467 colOffset = colOffsetMin < 0 ? -colOffsetMin : 0;
468 rowOffset = rowOffsetMin < 0 ? -rowOffsetMin : 0;
469 width = std::max(colOffsetMax + colOffset + 1, m_width);
470 height = std::max(rowOffsetMax + rowOffset + 1, m_height);
471}
472
473//-----------------------------------------------------------------------------------------------------------------------------------------
474
475void DlVertexingAlgorithm::DrawRing(float **canvas, const int row, const int col, const int inner, const int outer, const float weight) const
476{
477 // Set the starting position for each circle bounding the ring
478 int c1{inner}, r1{0}, c2{outer}, r2{0};
479 int inner2{inner * inner}, outer2{outer * outer};
480 while (c2 >= r2)
481 {
482 // Set the output pixel location
483 int rp2{r2}, cp2{c2};
484 // We're still within the octant for the inner ring, so use the inner pixel location (see Update comment below)
485 // Note also that the inner row is always the same as the outer row, so no need to define rp1
486 int cp1{c1};
487 if (c1 <= r1)
488 { // We've completed the arc of the inner ring already, so just move radially out from here (see Update comment below)
489 cp1 = r2;
490 }
491 // Fill the pixels from inner to outer in the current row and their mirror pixels in the other octants
492 for (int c = cp1; c <= cp2; ++c)
493 {
494 canvas[row + rp2][col + c] += weight;
495 if (rp2 != c)
496 canvas[row + c][col + rp2] += weight;
497 if (rp2 != 0 && cp2 != 0)
498 {
499 canvas[row - rp2][col - c] += weight;
500 if (rp2 != c)
501 canvas[row - c][col - rp2] += weight;
502 }
503 if (rp2 != 0)
504 {
505 canvas[row - rp2][col + c] += weight;
506 if (rp2 != c)
507 canvas[row + c][col - rp2] += weight;
508 }
509 if (cp2 != 0)
510 {
511 canvas[row + rp2][col - c] += weight;
512 if (rp2 != c)
513 canvas[row - c][col + rp2] += weight;
514 }
515 }
516 // Only update the inner location while it remains in the octant (outer ring also remains in the octant of course, but the logic of
517 // the update means that the inner ring can leave its octant before the outer ring is complete, so we need to stop that)
518 if (c1 > r1)
519 this->Update(inner2, c1, r1);
520 // Update the outer location - increase the row position with every step, decrease the column position if conditions are met
521 this->Update(outer2, c2, r2);
522 }
523}
524
525//-----------------------------------------------------------------------------------------------------------------------------------------
526
527void DlVertexingAlgorithm::Update(const int radius2, int &col, int &row) const
528{
529 // Bresenham midpoint circle algorithm to determine if we should update the column position
530 // This obscure looking block of code uses bit shifts and integer arithmetic to perform this check as efficiently as possible
531 const int a{1 - (col << 2)};
532 const int b{col * col + row * row - radius2 + (row << 2) + 1};
533 const int c{(a << 2) * b + a * a};
534 if (c < 0)
535 {
536 --col;
537 ++row;
538 }
539 else
540 ++row;
541}
542
543//-----------------------------------------------------------------------------------------------------------------------------------------
544
546{
547 const CaloHitList *pCaloHitList2D(nullptr);
548 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, "CaloHitList2D", pCaloHitList2D));
549 const MCParticleList *pMCParticleList(nullptr);
550 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pMCParticleList));
551
553 parameters.m_maxPhotonPropagation = std::numeric_limits<float>::max();
555 pMCParticleList, pCaloHitList2D, parameters, LArMCParticleHelper::IsBeamNeutrinoFinalState, mcToHitsMap);
556
557 return STATUS_CODE_SUCCESS;
558}
559
560//-----------------------------------------------------------------------------------------------------------------------------------------
561
563{
564 try
565 {
566 for (const auto &[mc, hits] : mcToHitsMap)
567 {
568 (void)hits;
569 mcHierarchy.push_back(mc);
571 }
572 }
573 catch (const StatusCodeException &e)
574 {
575 return e.GetStatusCode();
576 }
577
578 // Move the neutrino to the front of the list
579 auto pivot =
580 std::find_if(mcHierarchy.begin(), mcHierarchy.end(), [](const MCParticle *mc) -> bool { return LArMCParticleHelper::IsNeutrino(mc); });
581 (void)pivot;
582 if (pivot != mcHierarchy.end())
583 std::rotate(mcHierarchy.begin(), pivot, std::next(pivot));
584 else
585 return STATUS_CODE_NOT_FOUND;
586
587 return STATUS_CODE_SUCCESS;
588}
589
590//-----------------------------------------------------------------------------------------------------------------------------------------
591
592void DlVertexingAlgorithm::GetHitRegion(const CaloHitList &caloHitList, float &xMin, float &xMax, float &zMin, float &zMax) const
593{
594 xMin = std::numeric_limits<float>::max();
595 xMax = -std::numeric_limits<float>::max();
596 zMin = std::numeric_limits<float>::max();
597 zMax = -std::numeric_limits<float>::max();
598 // Find the range of x and z values in the view
599 for (const CaloHit *pCaloHit : caloHitList)
600 {
601 const float x{pCaloHit->GetPositionVector().GetX()};
602 const float z{pCaloHit->GetPositionVector().GetZ()};
603 xMin = std::min(x, xMin);
604 xMax = std::max(x, xMax);
605 zMin = std::min(z, zMin);
606 zMax = std::max(z, zMax);
607 }
608
609 if (caloHitList.empty())
610 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
611
612 const HitType view{caloHitList.front()->GetHitType()};
613 const bool isU{view == TPC_VIEW_U}, isV{view == TPC_VIEW_V}, isW{view == TPC_VIEW_W};
614 if (!(isU || isV || isW))
615 throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
616
617 // ATTN If wire w pitches vary between TPCs, exception will be raised in initialisation of lar pseudolayer plugin
618 const LArTPC *const pTPC(this->GetPandora().GetGeometry()->GetLArTPCMap().begin()->second);
619 const float pitch(view == TPC_VIEW_U ? pTPC->GetWirePitchU() : view == TPC_VIEW_V ? pTPC->GetWirePitchV() : pTPC->GetWirePitchW());
620
621 if (m_pass > 1)
622 {
623 const VertexList *pVertexList(nullptr);
624 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_inputVertexListName, pVertexList));
625 if (pVertexList->empty())
626 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
627 const CartesianVector &vertex{pVertexList->front()->GetPosition()};
628
629 // Get hit distribution left/right asymmetry
630 int nHitsLeft{0}, nHitsRight{0};
631 const double xVtx{vertex.GetX()};
632 for (const std::string &listname : m_caloHitListNames)
633 {
634 const CaloHitList *pCaloHitList(nullptr);
635 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, listname, pCaloHitList));
636 if (pCaloHitList->empty())
637 continue;
638 for (const CaloHit *const pCaloHit : *pCaloHitList)
639 {
640 const CartesianVector &pos{pCaloHit->GetPositionVector()};
641 if (pos.GetX() <= xVtx)
642 ++nHitsLeft;
643 else
644 ++nHitsRight;
645 }
646 }
647 const int nHitsTotal{nHitsLeft + nHitsRight};
648 if (nHitsTotal == 0)
649 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
650 const float xAsymmetry{nHitsLeft / static_cast<float>(nHitsTotal)};
651
652 // Vertices
654 double zVtx{0.};
655 if (isW)
656 zVtx += transform->YZtoW(vertex.GetY(), vertex.GetZ());
657 else if (isV)
658 zVtx += transform->YZtoV(vertex.GetY(), vertex.GetZ());
659 else
660 zVtx = transform->YZtoU(vertex.GetY(), vertex.GetZ());
661
662 // Get hit distribution upstream/downstream asymmetry
663 int nHitsUpstream{0}, nHitsDownstream{0};
664 for (const CaloHit *const pCaloHit : caloHitList)
665 {
666 const CartesianVector &pos{pCaloHit->GetPositionVector()};
667 if (pos.GetZ() <= zVtx)
668 ++nHitsUpstream;
669 else
670 ++nHitsDownstream;
671 }
672 const int nHitsViewTotal{nHitsUpstream + nHitsDownstream};
673 if (nHitsViewTotal == 0)
674 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
675 const float zAsymmetry{nHitsUpstream / static_cast<float>(nHitsViewTotal)};
676
677 const float xSpan{m_driftStep * (m_width - 1)};
678 xMin = xVtx - xAsymmetry * xSpan;
679 xMax = xMin + (m_driftStep * (m_width - 1));
680 const float zSpan{pitch * (m_height - 1)};
681 zMin = zVtx - zAsymmetry * zSpan;
682 zMax = zMin + zSpan;
683 }
684
685 // Avoid unreasonable rescaling of very small hit regions, pixels are assumed to be 0.5cm in x and wire pitch in z
686 // ATTN: Rescaling is to a size 1 pixel smaller than the intended image to ensure all hits fit within an imaged binned
687 // to be one pixel wider than this
688 const float xRange{xMax - xMin}, zRange{zMax - zMin};
689 const float minXSpan{m_driftStep * (m_width - 1)};
690 if (xRange < minXSpan)
691 {
692 const float padding{0.5f * (minXSpan - xRange)};
693 xMin -= padding;
694 xMax += padding;
695 }
696 const float minZSpan{pitch * (m_height - 1)};
697 if (zRange < minZSpan)
698 {
699 const float padding{0.5f * (minZSpan - zRange)};
700 zMin -= padding;
701 zMax += padding;
702 }
703}
704
705//-----------------------------------------------------------------------------------------------------------------------------------------
706
708{
709 const VertexList *pVertexList{nullptr};
710 std::string temporaryListName;
711 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pVertexList, temporaryListName));
712
713 for (const CartesianVector &position : positions)
714 {
715 PandoraContentApi::Vertex::Parameters parameters;
716 parameters.m_position = position;
717 parameters.m_vertexLabel = VERTEX_INTERACTION;
718 parameters.m_vertexType = VERTEX_3D;
719
720 const Vertex *pVertex(nullptr);
721 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pVertex));
722 }
725
726 return STATUS_CODE_SUCCESS;
727}
728
729//-----------------------------------------------------------------------------------------------------------------------------------------
730
731void DlVertexingAlgorithm::GetTrueVertexPosition(float &x, float &y, float &z) const
732{
733 const CartesianVector &trueVertex{this->GetTrueVertex()};
734 x = trueVertex.GetX();
735 y = trueVertex.GetY();
736 z = trueVertex.GetZ();
737}
738
739//-----------------------------------------------------------------------------------------------------------------------------------------
740
741void DlVertexingAlgorithm::GetTrueVertexPosition(float &x, float &u, float &v, float &w) const
742{
743 const CartesianVector &trueVertex{this->GetTrueVertex()};
745 x = trueVertex.GetX();
746 u = static_cast<float>(transform->YZtoU(trueVertex.GetY(), trueVertex.GetZ()));
747 v = static_cast<float>(transform->YZtoV(trueVertex.GetY(), trueVertex.GetZ()));
748 w = static_cast<float>(transform->YZtoW(trueVertex.GetY(), trueVertex.GetZ()));
749}
750
751//-----------------------------------------------------------------------------------------------------------------------------------------
752
754{
755 const MCParticleList *pMCParticleList{nullptr};
756 if (STATUS_CODE_SUCCESS == PandoraContentApi::GetCurrentList(*this, pMCParticleList) && pMCParticleList)
757 {
758 MCParticleVector primaries;
759 LArMCParticleHelper::GetPrimaryMCParticleList(pMCParticleList, primaries);
760 if (!primaries.empty())
761 {
762 const MCParticle *primary{primaries.front()};
763 const MCParticleList &parents{primary->GetParentList()};
764 if (parents.size() == 1)
765 {
766 const MCParticle *trueNeutrino{parents.front()};
767 if (LArMCParticleHelper::IsNeutrino(trueNeutrino))
768 return primaries.front()->GetVertex();
769 }
770 }
771 }
772
773 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
774}
775
776#ifdef MONITORING
777void DlVertexingAlgorithm::PopulateRootTree(const std::vector<VertexTuple> &vertexTuples, const pandora::CartesianPointVector &vertexCandidatesU,
778 const pandora::CartesianPointVector &vertexCandidatesV, const pandora::CartesianPointVector &vertexCandidatesW) const
779{
780 if (m_writeTree)
781 {
782 const MCParticleList *pMCParticleList{nullptr};
783 if (STATUS_CODE_SUCCESS == PandoraContentApi::GetCurrentList(*this, pMCParticleList))
784 {
785 if (pMCParticleList)
786 {
788 MCParticleVector primaries;
789 LArMCParticleHelper::GetPrimaryMCParticleList(pMCParticleList, primaries);
790 if (!primaries.empty())
791 {
792 const MCParticle *primary{primaries.front()};
793 const MCParticleList &parents{primary->GetParentList()};
794 if (parents.size() == 1)
795 {
796 const MCParticle *trueNeutrino{parents.front()};
797 if (LArMCParticleHelper::IsNeutrino(trueNeutrino))
798 {
800 const CartesianVector &trueVertex{primaries.front()->GetVertex()};
802 {
803 const CartesianVector &recoVertex{vertexTuples.front().GetPosition()};
804 const float tx{trueVertex.GetX()};
805 const float tu{static_cast<float>(transform->YZtoU(trueVertex.GetY(), trueVertex.GetZ()))};
806 const float tv{static_cast<float>(transform->YZtoV(trueVertex.GetY(), trueVertex.GetZ()))};
807 const float tw{static_cast<float>(transform->YZtoW(trueVertex.GetY(), trueVertex.GetZ()))};
808 const float rx_u{vertexCandidatesU.front().GetX()};
809 const float ru{vertexCandidatesU.front().GetZ()};
810 const float rx_v{vertexCandidatesV.front().GetX()};
811 const float rv{vertexCandidatesV.front().GetZ()};
812 const float rx_w{vertexCandidatesW.front().GetX()};
813 const float rw{vertexCandidatesW.front().GetZ()};
814 const float dr_u{std::sqrt((rx_u - tx) * (rx_u - tx) + (ru - tu) * (ru - tu))};
815 const float dr_v{std::sqrt((rx_v - tx) * (rx_v - tx) + (rv - tv) * (rv - tv))};
816 const float dr_w{std::sqrt((rx_w - tx) * (rx_w - tx) + (rw - tw) * (rw - tw))};
817 const CartesianVector &dv{recoVertex - trueVertex};
818 const float dr{dv.GetMagnitude()};
819 const float dx{dv.GetX()}, dy{dv.GetY()}, dz{dv.GetZ()};
820 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_rootTreeName, "event", m_event));
821 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_rootTreeName, "pass", m_pass));
822 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_rootTreeName, "dr_u", dr_u));
823 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_rootTreeName, "dr_v", dr_v));
824 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_rootTreeName, "dr_w", dr_w));
825 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_rootTreeName, "dr", dr));
826 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_rootTreeName, "dx", dx));
827 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_rootTreeName, "dy", dy));
828 PANDORA_MONITORING_API(SetTreeVariable(this->GetPandora(), m_rootTreeName, "dz", dz));
830 }
831 }
832 }
833 }
834 }
835 }
836 }
837}
838#endif
839
840//-----------------------------------------------------------------------------------------------------------------------------------------
841
843{
844 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "TrainingMode", m_trainingMode));
845 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "Visualise", m_visualise));
846 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "Pass", m_pass));
847 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ImageHeight", m_height));
848 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "ImageWidth", m_width));
849 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "DriftStep", m_driftStep));
850 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "DistanceThresholds", m_thresholds));
851 m_nClasses = m_thresholds.size() - 1;
852 if (m_pass > 1)
853 {
854 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "InputVertexListName", m_inputVertexListName));
855 }
856
857 if (m_trainingMode)
858 {
859 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "TrainingOutputFileName", m_trainingOutputFile));
860 }
861 else
862 {
863 std::string modelName;
864 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "ModelFileNameU", modelName));
865 modelName = LArFileHelper::FindFileInPath(modelName, "FW_SEARCH_PATH");
867 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "ModelFileNameV", modelName));
868 modelName = LArFileHelper::FindFileInPath(modelName, "FW_SEARCH_PATH");
870 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "ModelFileNameW", modelName));
871 modelName = LArFileHelper::FindFileInPath(modelName, "FW_SEARCH_PATH");
873 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "WriteTree", m_writeTree));
874 if (m_writeTree)
875 {
876 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RootTreeName", m_rootTreeName));
877 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RootFileName", m_rootFileName));
878 }
879 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "OutputVertexListName", m_outputVertexListName));
880 }
881
883 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadVectorOfValues(xmlHandle, "CaloHitListNames", m_caloHitListNames));
884 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "VolumeType", m_volumeType));
885
886 return STATUS_CODE_SUCCESS;
887}
888
889//-----------------------------------------------------------------------------------------------------------------------------------------
890//-----------------------------------------------------------------------------------------------------------------------------------------
891
893 const Pandora &pandora, const CartesianVector &vertexU, const CartesianVector &vertexV, const CartesianVector &vertexW) :
894 m_pos{0.f, 0.f, 0.f},
895 m_chi2{0.f}
896{
898 if (m_chi2 > 1.f)
899 {
900 CartesianVector vertexUV(0.f, 0.f, 0.f);
901 float chi2UV{0.f};
902 LArGeometryHelper::MergeTwoPositions3D(pandora, TPC_VIEW_U, TPC_VIEW_V, vertexU, vertexV, vertexUV, chi2UV);
903
904 CartesianVector vertexUW(0.f, 0.f, 0.f);
905 float chi2UW{0.f};
906 LArGeometryHelper::MergeTwoPositions3D(pandora, TPC_VIEW_U, TPC_VIEW_W, vertexU, vertexW, vertexUW, chi2UW);
907
908 CartesianVector vertexVW(0.f, 0.f, 0.f);
909 float chi2VW{0.f};
910 LArGeometryHelper::MergeTwoPositions3D(pandora, TPC_VIEW_V, TPC_VIEW_W, vertexV, vertexW, vertexVW, chi2VW);
911
912 if (chi2UV < m_chi2)
913 {
914 m_pos = vertexUV;
915 m_chi2 = chi2UV;
916 }
917 if (chi2UW < m_chi2)
918 {
919 m_pos = vertexUW;
920 m_chi2 = chi2UW;
921 }
922 if (chi2VW < m_chi2)
923 {
924 m_pos = vertexVW;
925 m_chi2 = chi2VW;
926 }
927 }
928 // std::cout << "Merging 3, position (" << m_pos.GetX() << ", " << m_pos.GetY() << ", " << m_pos.GetZ() << ") with chi2 " << m_chi2 <<
929 // std::endl;
930}
931
932//-----------------------------------------------------------------------------------------------------------------------------------------
933
935 const Pandora &pandora, const CartesianVector &vertex1, const CartesianVector &vertex2, const HitType view1, const HitType view2) :
936 m_pos{0.f, 0.f, 0.f},
937 m_chi2{0.f}
938{
939 LArGeometryHelper::MergeTwoPositions3D(pandora, view1, view2, vertex1, vertex2, m_pos, m_chi2);
940 std::cout << "Merging 2, position (" << m_pos.GetX() << ", " << m_pos.GetY() << ", " << m_pos.GetZ() << ") with chi2 " << m_chi2 << std::endl;
941}
942
943//-----------------------------------------------------------------------------------------------------------------------------------------
944
946{
947 return m_pos;
948}
949
950//-----------------------------------------------------------------------------------------------------------------------------------------
951
953{
954 return m_chi2;
955}
956
957//-----------------------------------------------------------------------------------------------------------------------------------------
958
960{
961 const float x{m_pos.GetX()}, y{m_pos.GetY()}, z{m_pos.GetZ()};
962 return "3D pos: (" + std::to_string(x) + ", " + std::to_string(y) + ", " + std::to_string(z) + ") X2 = " + std::to_string(m_chi2);
963}
964
965} // namespace lar_dl_content
#define PANDORA_MONITORING_API(command)
Header file for the file helper class.
Header file for the geometry helper class.
Header file for the vertex helper class.
#define PANDORA_THROW_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:43
#define PANDORA_RETURN_RESULT_IF_AND_IF(StatusCode1, StatusCode2, Operator, Command)
Definition StatusCodes.h:31
#define PANDORA_RETURN_RESULT_IF(StatusCode1, Operator, Command)
Definition StatusCodes.h:19
static pandora::StatusCode ReplaceCurrentList(const pandora::Algorithm &algorithm, const std::string &newListName)
Replace the current list with a pre-saved list; use this new list as a permanent replacement for the ...
static pandora::StatusCode CreateTemporaryListAndSetCurrent(const pandora::Algorithm &algorithm, const T *&pT, std::string &temporaryListName)
Create a temporary list and set it to be the current list, enabling object creation.
static pandora::StatusCode GetCurrentList(const pandora::Algorithm &algorithm, const T *&pT)
Get the current list.
static pandora::StatusCode GetList(const pandora::Algorithm &algorithm, const std::string &listName, const T *&pT)
Get a named list.
static std::string FindFileInPath(const std::string &unqualifiedFileName, const std::string &environmentVariable, const std::string &delimiter=":")
Find the fully-qualified file name by searching through a list of delimiter-separated paths in a name...
static void MergeTwoPositions3D(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const pandora::CartesianVector &position1, const pandora::CartesianVector &position2, pandora::CartesianVector &position3D, float &chiSquared)
Merge 2D positions from two views to give unified 3D position.
static void MergeThreePositions3D(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const pandora::HitType view3, const pandora::CartesianVector &position1, const pandora::CartesianVector &position2, const pandora::CartesianVector &position3, pandora::CartesianVector &position3D, float &chiSquared)
Merge 2D positions from three views to give unified 3D position.
float m_maxPhotonPropagation
the maximum photon propagation length
static void GetAllAncestorMCParticles(const pandora::MCParticle *const pMCParticle, pandora::MCParticleList &ancestorMCParticleList)
Get all ancestor mc particles.
static void GetPrimaryMCParticleList(const pandora::MCParticleList *const pMCParticleList, pandora::MCParticleVector &mcPrimaryVector)
Get vector of primary MC particles from an input list of MC particles.
static bool IsNeutrino(const pandora::MCParticle *const pMCParticle)
Whether a mc particle is a neutrino or antineutrino.
static void SelectReconstructableMCParticles(const pandora::MCParticleList *pMCParticleList, const pandora::CaloHitList *pCaloHitList, const PrimaryParameters &parameters, std::function< bool(const pandora::MCParticle *const)> fCriteria, MCContributionMap &selectedMCParticlesToHitsMap)
Select target, reconstructable mc particles that match given criteria.
std::unordered_map< const pandora::MCParticle *, pandora::CaloHitList > MCContributionMap
static unsigned int GetNuanceCode(const pandora::MCParticle *const pMCParticle)
Get the nuance code of an MCParticle.
static bool IsBeamNeutrinoFinalState(const pandora::MCParticle *const pMCParticle)
Returns true if passed a primary neutrino final state MCParticle.
MvaTypes::MvaFeatureVector MvaFeatureVector
static pandora::StatusCode ProduceTrainingExample(const std::string &trainingOutputFile, const bool result, TCONTAINER &&featureContainer)
Produce a training example with the given features and result.
static bool IsInFiducialVolume(const pandora::Pandora &pandora, const pandora::CartesianVector &vertex, const std::string &detector)
Determine if a vertex is within a detector's fiducial volume. This throws a STATUS_CODE_INVALID_PARAM...
const pandora::CartesianVector & GetPosition() const
pandora::CartesianVector m_pos
Calculated 3D position.
float m_chi2
Chi squared of calculated position.
VertexTuple(const pandora::Pandora &pandora, const pandora::CartesianVector &vertexU, const pandora::CartesianVector &vertexV, const pandora::CartesianVector &vertexW)
pandora::StatusCode Run()
Run the algorithm.
void DrawRing(float **canvas, const int row, const int col, const int inner, const int outer, const float weight) const
Add a filled ring to the specified canvas. The ring has an inner radius based on the minimum predicte...
pandora::StatusCode MakeCandidateVertexList(const pandora::CartesianPointVector &positions)
Create a vertex list from the candidate vertices.
const pandora::CartesianVector & GetTrueVertex() const
Retrieve the true neutrino vertex.
LArDLHelper::TorchModel m_modelW
The model for the W view.
bool m_visualise
Whether or not to visualise the candidate vertices.
std::string m_outputVertexListName
Output vertex list name.
std::string m_rootTreeName
The ROOT tree name.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Read the algorithm settings.
int m_pass
The pass of the train/infer step.
pandora::StatusCode MakeWirePlaneCoordinatesFromCanvas(float **canvas, const int canvasWidth, const int canvasHeight, const int columnOffset, const int rowOffset, const pandora::HitType view, const float xMin, const float xMax, const float zMin, const float zMax, pandora::CartesianPointVector &positionVector) const
LArDLHelper::TorchModel m_modelV
The model for the V view.
pandora::StatusCode MakeNetworkInputFromHits(const pandora::CaloHitList &caloHits, const pandora::HitType view, const float xMin, const float xMax, const float zMin, const float zMax, LArDLHelper::TorchInput &networkInput, PixelVector &pixelVector) const
int m_nClasses
The number of distance classes.
float m_driftStep
The size of a pixel in the drift direction in cm (most relevant in pass 2)
std::string m_inputVertexListName
Input vertex list name if 2nd pass.
LArDLHelper::TorchModel m_modelU
The model for the U view.
std::string m_trainingOutputFile
Output file name for training examples.
pandora::StatusCode GetMCToHitsMap(LArMCParticleHelper::MCContributionMap &mcToHitsMap) const
bool m_writeTree
Whether or not to write validation details to a ROOT tree.
void Update(const int radius, int &col, int &row) const
Update the coordinates along the loci of a circle. When drawing the ring we need an efficient means t...
int m_height
The height of the images.
pandora::StringVector m_caloHitListNames
Names of input calo hit lists.
std::string m_volumeType
The name of the fiducial volume type for the monitoring output.
void GetHitRegion(const pandora::CaloHitList &caloHitList, float &xMin, float &xMax, float &zMin, float &zMax) const
void GetCanvasParameters(const LArDLHelper::TorchOutput &networkOutput, const PixelVector &pixelVector, int &columnOffset, int &rowOffset, int &width, int &height) const
Determines the parameters of the canvas for extracting the vertex location. The network predicts the ...
void GetTrueVertexPosition(float &x, float &y, float &z) const
Retrieve the true neutrino vertex position.
std::string m_rootFileName
The ROOT file name.
std::vector< double > m_thresholds
Distance class thresholds.
pandora::StatusCode CompleteMCHierarchy(const LArMCParticleHelper::MCContributionMap &mcToHitsMap, pandora::MCParticleList &mcHierarchy) const
static void InitialiseInput(const at::IntArrayRef dimensions, TorchInput &tensor)
Create a torch input tensor.
std::vector< torch::jit::IValue > TorchInputVector
Definition LArDLHelper.h:27
static pandora::StatusCode LoadModel(const std::string &filename, TorchModel &model)
Loads a deep learning model.
static void Forward(TorchModel &model, const TorchInputVector &input, TorchOutput &output)
Run a deep learning model.
CaloHit class.
Definition CaloHit.h:26
CartesianVector class.
float GetX() const
Get the cartesian x coordinate.
float GetZ() const
Get the cartesian z coordinate.
float GetMagnitude() const
Get the magnitude.
float GetY() const
Get the cartesian y coordinate.
LArTPC class.
Definition LArTPC.h:26
float GetWirePitchU() const
Get the u wire pitch, units mm.
Definition LArTPC.h:217
float GetWirePitchV() const
Get the v wire pitch, units mm.
Definition LArTPC.h:224
float GetWirePitchW() const
Get the w wire pitch, units mm.
Definition LArTPC.h:231
LArTransformationPlugin class.
virtual double YZtoW(const double y, const double z) const =0
Transform from (Y,Z) to W position.
MCParticle class.
Definition MCParticle.h:26
const CartesianVector & GetVertex() const
Get the production vertex of the mc particle, units mm.
Definition MCParticle.h:257
const MCParticleList & GetParentList() const
Get list of parents of mc particle.
Definition MCParticle.h:299
Pandora class.
Definition Pandora.h:40
const PluginManager * GetPlugins() const
Get the pandora plugin instance, providing access to user registered functions and calculators.
Definition Pandora.cc:196
const LArTransformationPlugin * GetLArTransformationPlugin() const
Get the address of the lar transformation plugin.
const Pandora & GetPandora() const
Get the associated pandora instance.
Definition Process.h:116
StatusCodeException class.
StatusCode GetStatusCode() const
Get status code.
Vertex class.
Definition Vertex.h:26
static StatusCode ReadVectorOfValues(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, std::vector< T > &vector)
Read a vector of values from a (space separated) list in an xml element.
Definition XmlHelper.h:229
static StatusCode ReadValue(const TiXmlHandle &xmlHandle, const std::string &xmlElementName, T &t)
Read a value from an xml element.
Definition XmlHelper.h:136
HitType
Calorimeter hit type enum.
MANAGED_CONTAINER< const MCParticle * > MCParticleList
std::vector< CartesianVector > CartesianPointVector
MANAGED_CONTAINER< const CaloHit * > CaloHitList
std::vector< const MCParticle * > MCParticleVector
MANAGED_CONTAINER< const Vertex * > VertexList
StatusCode
The StatusCode enum.