12 #include <torch/script.h> 13 #include <torch/torch.h> 28 DlVertexingAlgorithm::DlVertexingAlgorithm() :
29 m_trainingMode{
false},
39 m_rng(static_cast<std::mt19937::result_type>(std::chrono::high_resolution_clock::now().time_since_epoch().count())),
52 catch (StatusCodeException
e)
54 std::cout <<
"VertexAssessmentAlgorithm: Unable to write to ROOT tree" << std::endl;
68 return STATUS_CODE_SUCCESS;
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));
79 std::map<HitType, float> wireMin, wireMax;
80 float driftMin{std::numeric_limits<float>::max()}, driftMax{-std::numeric_limits<float>::max()};
83 const CaloHitList *pCaloHitList{
nullptr};
84 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*
this, listname, pCaloHitList));
85 if (pCaloHitList->empty())
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);
94 for (
const std::string &listname : m_caloHitListNames)
96 const CaloHitList *pCaloHitList(
nullptr);
97 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*
this, listname, pCaloHitList));
98 if (pCaloHitList->empty())
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;
106 CartesianPointVector vertices;
107 for (
const MCParticle *mc : hierarchy)
109 if (LArMCParticleHelper::IsNeutrino(mc))
110 vertices.push_back(mc->GetVertex());
112 if (vertices.empty())
114 const CartesianVector &
vertex{vertices.front()};
116 const unsigned long nVertices{1};
117 unsigned long nHits{0};
118 const unsigned int nuance{LArMCParticleHelper::GetNuanceCode(hierarchy.front())};
121 const LArTransformationPlugin *transform{this->GetPandora().GetPlugins()->GetLArTransformationPlugin()};
122 const double xVtx{
vertex.GetX()};
132 double xMin{driftMin}, xMax{driftMax}, zMin{wireMin[view]}, zMax{wireMax[view]};
135 if (!(xVtx > (xMin - 1.
f) && xVtx < (xMax + 1.
f) && zVtx > (zMin - 1.
f) && zVtx < (zMax + 1.
f)))
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);
144 featureVector.emplace_back(xMin);
145 featureVector.emplace_back(xMax);
146 featureVector.emplace_back(zMin);
147 featureVector.emplace_back(zMax);
149 for (
const CaloHit *pCaloHit : *pCaloHitList)
151 const float x{pCaloHit->GetPositionVector().GetX()},
z{pCaloHit->GetPositionVector().GetZ()}, adc{pCaloHit->GetMipEquivalentEnergy()};
153 if (
m_pass > 1 && (x < xMin || x > xMax || z < zMin || z > zMax))
155 featureVector.emplace_back(static_cast<double>(
x));
156 featureVector.emplace_back(static_cast<double>(
z));
157 featureVector.emplace_back(static_cast<double>(adc));
160 featureVector.insert(featureVector.begin() + 8,
static_cast<double>(nHits));
163 LArMvaHelper::ProduceTrainingExample(trainingFilename,
true, featureVector);
166 return STATUS_CODE_SUCCESS;
176 std::map<HitType, float> wireMin, wireMax;
177 float driftMin{std::numeric_limits<float>::max()}, driftMax{-std::numeric_limits<float>::max()};
180 const CaloHitList *pCaloHitList{
nullptr};
181 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*
this, listname, pCaloHitList));
182 if (pCaloHitList->empty())
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);
192 CartesianPointVector vertexCandidatesU, vertexCandidatesV, vertexCandidatesW;
193 for (
const std::string &listName : m_caloHitListNames)
195 const CaloHitList *pCaloHitList{
nullptr};
196 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*
this, listName, pCaloHitList));
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;
205 this->
MakeNetworkInputFromHits(*pCaloHitList, view, driftMin, driftMax, wireMin[view], wireMax[view], input, pixelVector);
209 inputs.push_back(input);
218 int colOffset{0}, rowOffset{0}, canvasWidth{
m_width}, canvasHeight{
m_height};
219 this->
GetCanvasParameters(output, pixelVector, colOffset, rowOffset, canvasWidth, canvasHeight);
221 float **canvas{
new float *[canvasHeight]};
222 for (
int row = 0; row < canvasHeight; ++row)
223 canvas[row] =
new float[canvasWidth]{};
226 auto classes{torch::argmax(output, 1)};
228 auto classesAccessor{classes.accessor<long, 3>()};
230 std::map<int, bool> haveSeenMap;
231 for (
const auto &[row,
col] : pixelVector)
233 const auto cls{classesAccessor[0][row][
col]};
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));
242 CartesianPointVector positionVector;
244 canvas, canvasWidth, canvasHeight, colOffset, rowOffset, view, driftMin, driftMax, wireMin[view], wireMax[view], positionVector);
246 vertexCandidatesU.emplace_back(positionVector.front());
248 vertexCandidatesV.emplace_back(positionVector.front());
250 vertexCandidatesW.emplace_back(positionVector.front());
255 PANDORA_MONITORING_API(SetEveDisplayParameters(this->GetPandora(),
true, DETECTOR_VIEW_XZ, -1.
f, 1.
f, 1.
f));
258 float x{0.f}, u{0.f}, v{0.f},
w{0.f};
262 const CartesianVector trueVertex(
x, 0.
f, u);
263 PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &trueVertex,
"U(true)", BLUE, 3));
267 const CartesianVector trueVertex(
x, 0.
f, v);
268 PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &trueVertex,
"V(true)", BLUE, 3));
272 const CartesianVector trueVertex(
x, 0.
f,
w);
273 PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &trueVertex,
"W(true)", BLUE, 3));
276 catch (StatusCodeException &
e)
278 std::cerr <<
"DlVertexingAlgorithm: Warning. Couldn't find true vertex." << std::endl;
280 for (
const auto &pos : positionVector)
282 std::string label{isU ?
"U" : isV ?
"V" :
"W"};
283 PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &pos, label, RED, 3));
285 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
289 for (
int row = 0; row < canvasHeight; ++row)
290 delete[] canvas[row];
295 if (vertexCandidatesU.empty())
297 if (vertexCandidatesV.empty())
299 if (vertexCandidatesW.empty())
301 std::vector<VertexTuple> vertexTuples;
302 CartesianPointVector candidates3D;
303 if (nEmptyLists == 0)
305 vertexTuples.emplace_back(
VertexTuple(this->GetPandora(), vertexCandidatesU.front(), vertexCandidatesV.front(), vertexCandidatesW.front()));
307 else if (nEmptyLists == 1)
309 if (vertexCandidatesU.empty())
311 vertexTuples.emplace_back(
VertexTuple(this->GetPandora(), vertexCandidatesV.front(), vertexCandidatesW.front(), TPC_VIEW_V, TPC_VIEW_W));
313 else if (vertexCandidatesV.empty())
315 vertexTuples.emplace_back(
VertexTuple(this->GetPandora(), vertexCandidatesU.front(), vertexCandidatesW.front(), TPC_VIEW_U, TPC_VIEW_W));
319 vertexTuples.emplace_back(
VertexTuple(this->GetPandora(), vertexCandidatesU.front(), vertexCandidatesV.front(), TPC_VIEW_U, TPC_VIEW_V));
324 std::cout <<
"Insufficient 2D vertices to reconstruct a 3D vertex" << std::endl;
325 return STATUS_CODE_NOT_FOUND;
330 PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &vertexTuples.front().GetPosition(),
"candidate", GREEN, 1));
333 if (!vertexTuples.empty())
335 const CartesianVector &
vertex{vertexTuples.front().GetPosition()};
336 CartesianPointVector vertexCandidates;
337 vertexCandidates.emplace_back(
vertex);
342 std::cout <<
"Insufficient 2D vertices to reconstruct a 3D vertex" << std::endl;
343 return STATUS_CODE_NOT_FOUND;
348 PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
351 return STATUS_CODE_SUCCESS;
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());
364 std::vector<double> xBinEdges(
m_width + 1);
365 std::vector<double> zBinEdges(
m_height + 1);
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;
376 auto accessor = networkInput.accessor<float, 4>();
378 for (
const CaloHit *pCaloHit : caloHits)
380 const float x{pCaloHit->GetPositionVector().GetX()};
381 const float z{pCaloHit->GetPositionVector().GetZ()};
384 if (x < xMin || x > xMax || z < zMin || z > zMax)
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;
392 for (
int row = 0; row <
m_height; ++row)
396 const float value{accessor[0][0][row][
col]};
398 pixelVector.emplace_back(std::make_pair(row,
col));
402 return STATUS_CODE_SUCCESS;
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 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());
416 const double dz = ((zMax + 0.5f * pitch) - (zMin - 0.5
f * pitch)) /
m_height;
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)
424 best = canvas[row][
col];
429 const float x{
static_cast<float>((colBest - columnOffset) * dx + xMin)};
430 const float z{
static_cast<float>((rowBest - rowOffset) * dz + zMin)};
432 CartesianVector
pt(
x, 0.
f,
z);
433 positionVector.emplace_back(pt);
435 return STATUS_CODE_SUCCESS;
441 int &colOffset,
int &rowOffset,
int &width,
int &height)
const 446 auto classes{torch::argmax(networkOutput, 1)};
448 auto classesAccessor{classes.accessor<long, 3>()};
449 int colOffsetMin{0}, colOffsetMax{0}, rowOffsetMin{0}, rowOffsetMax{0};
450 for (
const auto &[row,
col] : pixelVector)
452 const auto cls{classesAccessor[0][row][
col]};
454 if (threshold > 0. && threshold < 1.)
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;
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);
478 int c1{inner}, r1{0},
c2{outer}, r2{0};
479 int inner2{inner * inner}, outer2{outer * outer};
483 int rp2{r2}, cp2{
c2};
492 for (
int c = cp1; c <= cp2; ++c)
494 canvas[row + rp2][col + c] +=
weight;
496 canvas[row + c][col + rp2] +=
weight;
497 if (rp2 != 0 && cp2 != 0)
499 canvas[row - rp2][col - c] +=
weight;
501 canvas[row - c][col - rp2] +=
weight;
505 canvas[row - rp2][col + c] +=
weight;
507 canvas[row + c][col - rp2] +=
weight;
511 canvas[row + rp2][col - c] +=
weight;
513 canvas[row - c][col + rp2] +=
weight;
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};
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));
554 LArMCParticleHelper::SelectReconstructableMCParticles(
555 pMCParticleList, pCaloHitList2D, parameters, LArMCParticleHelper::IsBeamNeutrinoFinalState, mcToHitsMap);
557 return STATUS_CODE_SUCCESS;
566 for (
const auto &[mc,
hits] : mcToHitsMap)
569 mcHierarchy.push_back(mc);
570 LArMCParticleHelper::GetAllAncestorMCParticles(mc, mcHierarchy);
573 catch (
const StatusCodeException &
e)
575 return e.GetStatusCode();
580 std::find_if(mcHierarchy.begin(), mcHierarchy.end(), [](
const MCParticle *mc) ->
bool {
return LArMCParticleHelper::IsNeutrino(mc); });
582 if (pivot != mcHierarchy.end())
583 std::rotate(mcHierarchy.begin(), pivot, std::next(pivot));
585 return STATUS_CODE_NOT_FOUND;
587 return STATUS_CODE_SUCCESS;
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();
599 for (
const CaloHit *pCaloHit : caloHitList)
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);
609 if (caloHitList.empty())
610 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
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);
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());
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()};
630 int nHitsLeft{0}, nHitsRight{0};
631 const double xVtx{
vertex.GetX()};
634 const CaloHitList *pCaloHitList(
nullptr);
635 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*
this, listname, pCaloHitList));
636 if (pCaloHitList->empty())
638 for (
const CaloHit *
const pCaloHit : *pCaloHitList)
640 const CartesianVector &pos{pCaloHit->GetPositionVector()};
641 if (pos.GetX() <= xVtx)
647 const int nHitsTotal{nHitsLeft + nHitsRight};
649 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
650 const float xAsymmetry{nHitsLeft /
static_cast<float>(nHitsTotal)};
653 const LArTransformationPlugin *transform{this->GetPandora().GetPlugins()->GetLArTransformationPlugin()};
663 int nHitsUpstream{0}, nHitsDownstream{0};
664 for (
const CaloHit *
const pCaloHit : caloHitList)
666 const CartesianVector &pos{pCaloHit->GetPositionVector()};
667 if (pos.GetZ() <= zVtx)
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)};
678 xMin = xVtx - xAsymmetry * xSpan;
680 const float zSpan{pitch * (
m_height - 1)};
681 zMin = zVtx - zAsymmetry * zSpan;
688 const float xRange{xMax - xMin}, zRange{zMax - zMin};
690 if (xRange < minXSpan)
692 const float padding{0.5f * (minXSpan - xRange)};
696 const float minZSpan{pitch * (
m_height - 1)};
697 if (zRange < minZSpan)
699 const float padding{0.5f * (minZSpan - zRange)};
710 std::string temporaryListName;
711 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*
this, pVertexList, temporaryListName));
713 for (
const CartesianVector &position : positions)
715 PandoraContentApi::Vertex::Parameters parameters;
716 parameters.m_position = position;
717 parameters.m_vertexLabel = VERTEX_INTERACTION;
718 parameters.m_vertexType = VERTEX_3D;
720 const Vertex *pVertex(
nullptr);
721 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*
this, parameters, pVertex));
723 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Vertex>(*
this,
m_outputVertexListName));
724 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Vertex>(*
this,
m_outputVertexListName));
726 return STATUS_CODE_SUCCESS;
734 x = trueVertex.GetX();
735 y = trueVertex.GetY();
736 z = trueVertex.GetZ();
744 const LArTransformationPlugin *transform{this->GetPandora().GetPlugins()->GetLArTransformationPlugin()};
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()));
755 const MCParticleList *pMCParticleList{
nullptr};
756 if (STATUS_CODE_SUCCESS == PandoraContentApi::GetCurrentList(*
this, pMCParticleList) && pMCParticleList)
759 LArMCParticleHelper::GetPrimaryMCParticleList(pMCParticleList, primaries);
760 if (!primaries.empty())
762 const MCParticle *primary{primaries.front()};
763 const MCParticleList &parents{primary->GetParentList()};
764 if (parents.size() == 1)
766 const MCParticle *trueNeutrino{parents.front()};
767 if (LArMCParticleHelper::IsNeutrino(trueNeutrino))
768 return primaries.front()->GetVertex();
773 throw StatusCodeException(STATUS_CODE_NOT_FOUND);
777 void DlVertexingAlgorithm::PopulateRootTree(
const std::vector<VertexTuple> &vertexTuples,
const pandora::CartesianPointVector &vertexCandidatesU,
778 const pandora::CartesianPointVector &vertexCandidatesV,
const pandora::CartesianPointVector &vertexCandidatesW)
const 782 const MCParticleList *pMCParticleList{
nullptr};
783 if (STATUS_CODE_SUCCESS == PandoraContentApi::GetCurrentList(*
this, pMCParticleList))
789 LArMCParticleHelper::GetPrimaryMCParticleList(pMCParticleList, primaries);
790 if (!primaries.empty())
792 const MCParticle *primary{primaries.front()};
793 const MCParticleList &parents{primary->GetParentList()};
794 if (parents.size() == 1)
796 const MCParticle *trueNeutrino{parents.front()};
797 if (LArMCParticleHelper::IsNeutrino(trueNeutrino))
799 const LArTransformationPlugin *transform{this->GetPandora().GetPlugins()->GetLArTransformationPlugin()};
800 const CartesianVector &trueVertex{primaries.front()->GetVertex()};
801 if (LArVertexHelper::IsInFiducialVolume(this->GetPandora(), trueVertex,
m_volumeType))
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()};
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));
829 PANDORA_MONITORING_API(FillTree(this->GetPandora(),
m_rootTreeName));
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));
854 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"InputVertexListName",
m_inputVertexListName));
859 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"TrainingOutputFileName",
m_trainingOutputFile));
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));
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));
879 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"OutputVertexListName",
m_outputVertexListName));
882 PANDORA_RETURN_RESULT_IF_AND_IF(
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));
886 return STATUS_CODE_SUCCESS;
893 const Pandora &
pandora,
const CartesianVector &vertexU,
const CartesianVector &vertexV,
const CartesianVector &vertexW) :
894 m_pos{0.f, 0.f, 0.f},
897 LArGeometryHelper::MergeThreePositions3D(pandora, TPC_VIEW_U, TPC_VIEW_V, TPC_VIEW_W, vertexU, vertexV, vertexW, m_pos, m_chi2);
900 CartesianVector vertexUV(0.
f, 0.
f, 0.
f);
902 LArGeometryHelper::MergeTwoPositions3D(pandora, TPC_VIEW_U, TPC_VIEW_V, vertexU, vertexV, vertexUV, chi2UV);
904 CartesianVector vertexUW(0.
f, 0.
f, 0.
f);
906 LArGeometryHelper::MergeTwoPositions3D(pandora, TPC_VIEW_U, TPC_VIEW_W, vertexU, vertexW, vertexUW, chi2UW);
908 CartesianVector vertexVW(0.
f, 0.
f, 0.
f);
910 LArGeometryHelper::MergeTwoPositions3D(pandora, TPC_VIEW_V, TPC_VIEW_W, vertexV, vertexW, vertexVW, chi2VW);
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},
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;
961 const float x{m_pos.GetX()},
y{m_pos.GetY()},
z{m_pos.GetZ()};
LArDLHelper::TorchModel m_modelU
The model for the U view.
const pandora::CartesianVector & GetTrueVertex() const
Retrieve the true neutrino vertex.
void GetHitRegion(const pandora::CaloHitList &caloHitList, float &xMin, float &xMax, float &zMin, float &zMax) const
std::vector< double > m_thresholds
Distance class thresholds.
std::unordered_map< const pandora::MCParticle *, pandora::CaloHitList > MCContributionMap
MvaTypes::MvaFeatureVector MvaFeatureVector
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...
pandora::StatusCode GetMCToHitsMap(LArMCParticleHelper::MCContributionMap &mcToHitsMap) const
bool m_visualise
Whether or not to visualise the candidate vertices.
int m_event
The current event number.
pandora::StatusCode PrepareTrainingSample()
pandora::StringVector m_caloHitListNames
Names of input calo hit lists.
std::string ToString() const
LArDLHelper::TorchModel m_modelV
The model for the V view.
float m_maxPhotonPropagation
the maximum photon propagation length
pandora::StatusCode CompleteMCHierarchy(const LArMCParticleHelper::MCContributionMap &mcToHitsMap, pandora::MCParticleList &mcHierarchy) const
std::string m_outputVertexListName
Output vertex list name.
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 ...
Header file for the geometry helper class.
std::mt19937 m_rng
The random number generator.
int m_nClasses
The number of distance classes.
std::string m_rootTreeName
The ROOT tree name.
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
bool m_writeTree
Whether or not to write validation details to a ROOT tree.
int m_height
The height of the images.
std::vector< art::Ptr< simb::MCParticle > > MCParticleVector
const pandora::CartesianVector & GetPosition() const
int m_pass
The pass of the train/infer step.
Header file for the file helper class.
pandora::StatusCode Run()
static void Forward(TorchModel &model, const TorchInputVector &input, TorchOutput &output)
Run a deep learning model.
void GetTrueVertexPosition(float &x, float &y, float &z) const
Retrieve the true neutrino vertex position.
std::string m_inputVertexListName
Input vertex list name if 2nd pass.
Header file for the vertex helper class.
bool m_trainingMode
Training mode.
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
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
LArDLHelper::TorchModel m_modelW
The model for the W 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
std::string m_trainingOutputFile
Output file name for training examples.
static pandora::StatusCode LoadModel(const std::string &filename, TorchModel &model)
Loads a deep learning model.
std::string m_rootFileName
The ROOT file name.
pandora::StatusCode Infer()
pandora::StatusCode MakeCandidateVertexList(const pandora::CartesianPointVector &positions)
Create a vertex list from the candidate vertices.
std::vector< Pixel > PixelVector
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
float m_driftStep
The size of a pixel in the drift direction in cm (most relevant in pass 2)
second_as<> second
Type of time stored in seconds, in double precision.
int m_width
The width of the images.
static void InitialiseInput(const at::IntArrayRef dimensions, TorchInput &tensor)
Create a torch input tensor.
std::list< Vertex > VertexList
virtual ~DlVertexingAlgorithm()
std::vector< torch::jit::IValue > TorchInputVector
VertexTuple(const pandora::Pandora &pandora, const pandora::CartesianVector &vertexU, const pandora::CartesianVector &vertexV, const pandora::CartesianVector &vertexW)
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...
std::string m_volumeType
The name of the fiducial volume type for the monitoring output.