LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
lar_dl_content::DlVertexingAlgorithm Class Reference

DeepLearningTrackShowerIdAlgorithm class. More...

#include "DlVertexingAlgorithm.h"

Inheritance diagram for lar_dl_content::DlVertexingAlgorithm:
lar_dl_content::DlVertexingBaseAlgorithm

Public Types

typedef std::map< std::pair< int, int >, std::vector< const pandora::CaloHit * > > PixelToCaloHitsMap
 

Public Member Functions

 DlVertexingAlgorithm ()
 Default constructor. More...
 
 ~DlVertexingAlgorithm ()
 

Protected Types

typedef std::pair< int, int > Pixel
 
typedef std::vector< PixelPixelVector
 

Protected Member Functions

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 distance that each pixel associated with a hit is located from the vertex, but says nothing about the direction. As a result, the ring describing the potential vertices associated with that hit can extend beyond the original canvas size. This function returns the size of the required canvas and the offset for the bottom left corner. More...
 

Protected Attributes

bool m_trainingMode
 Training mode. More...
 
std::string m_trainingOutputFile
 Output file name for training examples. More...
 
std::string m_inputVertexListName
 Input vertex list name if 2nd pass. More...
 
std::string m_outputVertexListName
 Output vertex list name. More...
 
pandora::StringVector m_caloHitListNames
 Names of input calo hit lists. More...
 
LArDLHelper::TorchModel m_modelU
 The model for the U view. More...
 
LArDLHelper::TorchModel m_modelV
 The model for the V view. More...
 
LArDLHelper::TorchModel m_modelW
 The model for the W view. More...
 
int m_pass
 The pass of the train/infer step. More...
 
int m_nClasses
 The number of distance classes. More...
 
int m_height
 The height of the images. More...
 
int m_width
 The width of the images. More...
 
float m_driftStep
 The size of a pixel in the drift direction in cm (most relevant in pass 2) More...
 
std::vector< double > m_thresholds
 Distance class thresholds. More...
 
std::string m_volumeType
 The name of the fiducial volume type for the monitoring output. More...
 

Private Member Functions

pandora::StatusCode Run ()
 
pandora::StatusCode ReadSettings (const pandora::TiXmlHandle xmlHandle)
 
pandora::StatusCode PrepareTrainingSample ()
 
pandora::StatusCode Infer ()
 
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
 
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 MakeCandidateVertexList (const pandora::CartesianPointVector &positions)
 Create a vertex list from the candidate vertices. More...
 

Private Attributes

int m_event
 The current event number. More...
 
bool m_visualise
 Whether or not to visualise the candidate vertices. More...
 
bool m_writeTree
 Whether or not to write validation details to a ROOT tree. More...
 
std::string m_rootTreeName
 The ROOT tree name. More...
 
std::string m_rootFileName
 The ROOT file name. More...
 
std::mt19937 m_rng
 The random number generator. More...
 

Detailed Description

DeepLearningTrackShowerIdAlgorithm class.

Definition at line 29 of file DlVertexingAlgorithm.h.

Member Typedef Documentation

typedef std::pair<int, int> lar_dl_content::DlVertexingBaseAlgorithm::Pixel
protectedinherited

Definition at line 41 of file DlVertexingBaseAlgorithm.h.

typedef std::map<std::pair<int, int>, std::vector<const pandora::CaloHit *> > lar_dl_content::DlVertexingBaseAlgorithm::PixelToCaloHitsMap
inherited

Definition at line 31 of file DlVertexingBaseAlgorithm.h.

typedef std::vector<Pixel> lar_dl_content::DlVertexingBaseAlgorithm::PixelVector
protectedinherited

Definition at line 42 of file DlVertexingBaseAlgorithm.h.

Constructor & Destructor Documentation

lar_dl_content::DlVertexingAlgorithm::DlVertexingAlgorithm ( )

Default constructor.

Definition at line 30 of file DlVertexingAlgorithm.cc.

References m_rng, m_visualise, and m_writeTree.

30  :
31  m_event{-1},
32  m_visualise{false},
33  m_writeTree{false},
34  m_rng(static_cast<std::mt19937::result_type>(std::chrono::high_resolution_clock::now().time_since_epoch().count()))
35 {
36 }
bool m_visualise
Whether or not to visualise the candidate vertices.
int m_event
The current event number.
std::mt19937 m_rng
The random number generator.
bool m_writeTree
Whether or not to write validation details to a ROOT tree.
lar_dl_content::DlVertexingAlgorithm::~DlVertexingAlgorithm ( )

Definition at line 38 of file DlVertexingAlgorithm.cc.

References e, m_rootFileName, m_rootTreeName, and m_writeTree.

39 {
40  if (m_writeTree)
41  {
42  try
43  {
44  PANDORA_MONITORING_API(SaveTree(this->GetPandora(), m_rootTreeName, m_rootFileName, "RECREATE"));
45  }
46  catch (StatusCodeException e)
47  {
48  std::cout << "VertexAssessmentAlgorithm: Unable to write to ROOT tree" << std::endl;
49  }
50  }
51 }
std::string m_rootTreeName
The ROOT tree name.
bool m_writeTree
Whether or not to write validation details to a ROOT tree.
std::string m_rootFileName
The ROOT file name.
Float_t e
Definition: plot.C:35

Member Function Documentation

void lar_dl_content::DlVertexingBaseAlgorithm::GetCanvasParameters ( const LArDLHelper::TorchOutput networkOutput,
const PixelVector pixelVector,
int &  columnOffset,
int &  rowOffset,
int &  width,
int &  height 
) const
protectedinherited

Determines the parameters of the canvas for extracting the vertex location. The network predicts the distance that each pixel associated with a hit is located from the vertex, but says nothing about the direction. As a result, the ring describing the potential vertices associated with that hit can extend beyond the original canvas size. This function returns the size of the required canvas and the offset for the bottom left corner.

Parameters
networkOutputThe TorchOutput object populated by the network inference step
pixelVectorThe vector of populated pixels
columnOffsetThe output column offset for the canvas
rowOffsetThe output row offset for the canvas
widthThe output width for the canvas
heightThe output height for the canvas

Definition at line 165 of file DlVertexingBaseAlgorithm.cc.

References col, lar_dl_content::DlVertexingBaseAlgorithm::m_height, lar_dl_content::DlVertexingBaseAlgorithm::m_thresholds, and lar_dl_content::DlVertexingBaseAlgorithm::m_width.

Referenced by Infer(), and lar_dl_content::DlSecondaryVertexingAlgorithm::Infer().

167 {
168  const double scaleFactor{std::sqrt(m_height * m_height + m_width * m_width)};
169  // output is a 1 x num_classes x height x width tensor
170  // we want the maximum value in the num_classes dimension (1) for every pixel
171  auto classes{torch::argmax(networkOutput, 1)};
172  // the argmax result is a 1 x height x width tensor where each element is a class id
173  auto classesAccessor{classes.accessor<int64_t, 3>()};
174  int colOffsetMin{0}, colOffsetMax{0}, rowOffsetMin{0}, rowOffsetMax{0};
175  for (const auto &[row, col] : pixelVector)
176  {
177  const auto cls{classesAccessor[0][row][col]};
178  const double threshold{m_thresholds[cls]};
179  if (threshold > 0. && threshold < 1.)
180  {
181  const int distance = static_cast<int>(std::round(std::ceil(scaleFactor * threshold)));
182  if ((row - distance) < rowOffsetMin)
183  rowOffsetMin = row - distance;
184  if ((row + distance) > rowOffsetMax)
185  rowOffsetMax = row + distance;
186  if ((col - distance) < colOffsetMin)
187  colOffsetMin = col - distance;
188  if ((col + distance) > colOffsetMax)
189  colOffsetMax = col + distance;
190  }
191  }
192  colOffset = colOffsetMin < 0 ? -colOffsetMin : 0;
193  rowOffset = rowOffsetMin < 0 ? -rowOffsetMin : 0;
194  width = std::max(colOffsetMax + colOffset + 1, m_width);
195  height = std::max(rowOffsetMax + rowOffset + 1, m_height);
196 }
std::vector< double > m_thresholds
Distance class thresholds.
Int_t col[ntarg]
Definition: Style.C:29
void lar_dl_content::DlVertexingBaseAlgorithm::GetHitRegion ( const pandora::CaloHitList &  caloHitList,
float &  xMin,
float &  xMax,
float &  zMin,
float &  zMax 
) const
protectedinherited

Definition at line 50 of file DlVertexingBaseAlgorithm.cc.

References util::begin(), lar_dl_content::DlVertexingBaseAlgorithm::m_caloHitListNames, lar_dl_content::DlVertexingBaseAlgorithm::m_driftStep, lar_dl_content::DlVertexingBaseAlgorithm::m_height, lar_dl_content::DlVertexingBaseAlgorithm::m_inputVertexListName, lar_dl_content::DlVertexingBaseAlgorithm::m_pass, lar_dl_content::DlVertexingBaseAlgorithm::m_width, x, and z.

Referenced by Infer(), lar_dl_content::DlSecondaryVertexingAlgorithm::Infer(), PrepareTrainingSample(), and lar_dl_content::DlSecondaryVertexingAlgorithm::PrepareTrainingSample().

51 {
52  xMin = std::numeric_limits<float>::max();
53  xMax = -std::numeric_limits<float>::max();
54  zMin = std::numeric_limits<float>::max();
55  zMax = -std::numeric_limits<float>::max();
56  // Find the range of x and z values in the view
57  for (const CaloHit *pCaloHit : caloHitList)
58  {
59  const float x{pCaloHit->GetPositionVector().GetX()};
60  const float z{pCaloHit->GetPositionVector().GetZ()};
61  xMin = std::min(x, xMin);
62  xMax = std::max(x, xMax);
63  zMin = std::min(z, zMin);
64  zMax = std::max(z, zMax);
65  }
66 
67  if (caloHitList.empty())
68  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
69 
70  const HitType view{caloHitList.front()->GetHitType()};
71  const bool isU{view == TPC_VIEW_U}, isV{view == TPC_VIEW_V}, isW{view == TPC_VIEW_W};
72  if (!(isU || isV || isW))
73  throw StatusCodeException(STATUS_CODE_NOT_ALLOWED);
74 
75  // ATTN If wire w pitches vary between TPCs, exception will be raised in initialisation of lar pseudolayer plugin
76  const LArTPC *const pTPC(this->GetPandora().GetGeometry()->GetLArTPCMap().begin()->second);
77  const float pitch(view == TPC_VIEW_U ? pTPC->GetWirePitchU() : view == TPC_VIEW_V ? pTPC->GetWirePitchV() : pTPC->GetWirePitchW());
78 
79  if (m_pass > 1)
80  {
81  const VertexList *pVertexList(nullptr);
82  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_inputVertexListName, pVertexList));
83  if (pVertexList->empty())
84  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
85  const CartesianVector &vertex{pVertexList->front()->GetPosition()};
86 
87  // Get hit distribution left/right asymmetry
88  int nHitsLeft{0}, nHitsRight{0};
89  const double xVtx{vertex.GetX()};
90  for (const std::string &listname : m_caloHitListNames)
91  {
92  const CaloHitList *pCaloHitList(nullptr);
93  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, listname, pCaloHitList));
94  if (pCaloHitList->empty())
95  continue;
96  for (const CaloHit *const pCaloHit : *pCaloHitList)
97  {
98  const CartesianVector &pos{pCaloHit->GetPositionVector()};
99  if (pos.GetX() <= xVtx)
100  ++nHitsLeft;
101  else
102  ++nHitsRight;
103  }
104  }
105  const int nHitsTotal{nHitsLeft + nHitsRight};
106  if (nHitsTotal == 0)
107  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
108  const float xAsymmetry{nHitsLeft / static_cast<float>(nHitsTotal)};
109 
110  // Vertices
111  const LArTransformationPlugin *transform{this->GetPandora().GetPlugins()->GetLArTransformationPlugin()};
112  double zVtx{0.};
113  if (isW)
114  zVtx += transform->YZtoW(vertex.GetY(), vertex.GetZ());
115  else if (isV)
116  zVtx += transform->YZtoV(vertex.GetY(), vertex.GetZ());
117  else
118  zVtx = transform->YZtoU(vertex.GetY(), vertex.GetZ());
119 
120  // Get hit distribution upstream/downstream asymmetry
121  int nHitsUpstream{0}, nHitsDownstream{0};
122  for (const CaloHit *const pCaloHit : caloHitList)
123  {
124  const CartesianVector &pos{pCaloHit->GetPositionVector()};
125  if (pos.GetZ() <= zVtx)
126  ++nHitsUpstream;
127  else
128  ++nHitsDownstream;
129  }
130  const int nHitsViewTotal{nHitsUpstream + nHitsDownstream};
131  if (nHitsViewTotal == 0)
132  throw StatusCodeException(STATUS_CODE_NOT_FOUND);
133  const float zAsymmetry{nHitsUpstream / static_cast<float>(nHitsViewTotal)};
134 
135  const float xSpan{m_driftStep * (m_width - 1)};
136  xMin = xVtx - xAsymmetry * xSpan;
137  xMax = xMin + (m_driftStep * (m_width - 1));
138  const float zSpan{pitch * (m_height - 1)};
139  zMin = zVtx - zAsymmetry * zSpan;
140  zMax = zMin + zSpan;
141  }
142 
143  // Avoid unreasonable rescaling of very small hit regions, pixels are assumed to be 0.5cm in x and wire pitch in z
144  // ATTN: Rescaling is to a size 1 pixel smaller than the intended image to ensure all hits fit within an imaged binned
145  // to be one pixel wider than this
146  const float xRange{xMax - xMin}, zRange{zMax - zMin};
147  const float minXSpan{m_driftStep * (m_width - 1)};
148  if (xRange < minXSpan)
149  {
150  const float padding{0.5f * (minXSpan - xRange)};
151  xMin -= padding;
152  xMax += padding;
153  }
154  const float minZSpan{pitch * (m_height - 1)};
155  if (zRange < minZSpan)
156  {
157  const float padding{0.5f * (minZSpan - zRange)};
158  zMin -= padding;
159  zMax += padding;
160  }
161 }
Float_t x
Definition: compare.C:6
int m_pass
The pass of the train/infer step.
Double_t z
Definition: plot.C:276
float m_driftStep
The size of a pixel in the drift direction in cm (most relevant in pass 2)
pandora::StringVector m_caloHitListNames
Names of input calo hit lists.
std::string m_inputVertexListName
Input vertex list name if 2nd pass.
HitType
Definition: HitType.h:12
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:82
std::list< Vertex > VertexList
Definition: DCEL.h:169
vertex reconstruction
StatusCode lar_dl_content::DlVertexingAlgorithm::Infer ( )
private

Definition at line 169 of file DlVertexingAlgorithm.cc.

References col, lar_dl_content::LArCanvasHelper::DrawRing(), f, lar_dl_content::LArDLHelper::Forward(), lar_dl_content::DlVertexingBaseAlgorithm::GetCanvasParameters(), lar_dl_content::DlVertexingBaseAlgorithm::GetHitRegion(), lar_dl_content::DlVertexingBaseAlgorithm::m_caloHitListNames, m_event, lar_dl_content::DlVertexingBaseAlgorithm::m_height, lar_dl_content::DlVertexingBaseAlgorithm::m_inputVertexListName, lar_dl_content::DlVertexingBaseAlgorithm::m_modelU, lar_dl_content::DlVertexingBaseAlgorithm::m_modelV, lar_dl_content::DlVertexingBaseAlgorithm::m_modelW, lar_dl_content::DlVertexingBaseAlgorithm::m_nClasses, lar_dl_content::DlVertexingBaseAlgorithm::m_pass, lar_dl_content::DlVertexingBaseAlgorithm::m_thresholds, m_visualise, lar_dl_content::DlVertexingBaseAlgorithm::m_width, MakeCandidateVertexList(), MakeNetworkInputFromHits(), MakeWirePlaneCoordinatesFromCanvas(), w, and x.

Referenced by Run().

170 {
171  if (m_pass == 1)
172  {
173  ++m_event;
174  }
175  else
176  {
177  // INFO: Check if there is a zoom in region for the second pass.
178  const VertexList *pVertexList(nullptr);
179  PandoraContentApi::GetList(*this, m_inputVertexListName, pVertexList);
180  if (pVertexList == nullptr || pVertexList->empty())
181  {
182  std::cout << "DLVertexing: Input vertex list is empty! Can't perform pass " << m_pass << std::endl;
183  return STATUS_CODE_SUCCESS;
184  }
185  }
186 
187  std::map<HitType, float> wireMin, wireMax;
188  float driftMin{std::numeric_limits<float>::max()}, driftMax{-std::numeric_limits<float>::max()};
189  for (const std::string &listname : m_caloHitListNames)
190  {
191  const CaloHitList *pCaloHitList{nullptr};
192  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, listname, pCaloHitList));
193  if (pCaloHitList->empty())
194  continue;
195 
196  HitType view{pCaloHitList->front()->GetHitType()};
197  float viewDriftMin{driftMin}, viewDriftMax{driftMax};
198  this->GetHitRegion(*pCaloHitList, viewDriftMin, viewDriftMax, wireMin[view], wireMax[view]);
199  driftMin = std::min(viewDriftMin, driftMin);
200  driftMax = std::max(viewDriftMax, driftMax);
201  }
202 
203  CartesianPointVector vertexCandidatesU, vertexCandidatesV, vertexCandidatesW;
204  for (const std::string &listName : m_caloHitListNames)
205  {
206  const CaloHitList *pCaloHitList{nullptr};
207  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, listName, pCaloHitList));
208 
209  HitType view{pCaloHitList->front()->GetHitType()};
210  const bool isU{view == TPC_VIEW_U}, isV{view == TPC_VIEW_V}, isW{view == TPC_VIEW_W};
211  if (!isU && !isV && !isW)
212  return STATUS_CODE_NOT_ALLOWED;
213 
215  PixelVector pixelVector;
216  this->MakeNetworkInputFromHits(*pCaloHitList, view, driftMin, driftMax, wireMin[view], wireMax[view], input, pixelVector);
217 
218  // Run the input through the trained model
220  inputs.push_back(input);
222  if (isU)
223  LArDLHelper::Forward(m_modelU, inputs, output);
224  else if (isV)
225  LArDLHelper::Forward(m_modelV, inputs, output);
226  else
227  LArDLHelper::Forward(m_modelW, inputs, output);
228 
229  int colOffset{0}, rowOffset{0}, canvasWidth{m_width}, canvasHeight{m_height};
230  this->GetCanvasParameters(output, pixelVector, colOffset, rowOffset, canvasWidth, canvasHeight);
231 
232  float **canvas{new float *[canvasHeight]};
233  for (int row = 0; row < canvasHeight; ++row)
234  canvas[row] = new float[canvasWidth]{};
235 
236  // we want the maximum value in the num_classes dimension (1) for every pixel
237  auto classes{torch::argmax(output, 1)};
238  // the argmax result is a 1 x height x width tensor where each element is a class id
239  auto classesAccessor{classes.accessor<int64_t, 3>()};
240  const double scaleFactor{std::sqrt(m_height * m_height + m_width * m_width)};
241  std::map<int, bool> haveSeenMap;
242  for (const auto &[row, col] : pixelVector)
243  {
244  const auto cls{classesAccessor[0][row][col]};
245  if (cls > 0 && cls < m_nClasses)
246  {
247  const int inner{static_cast<int>(std::round(std::ceil(scaleFactor * m_thresholds[cls - 1])))};
248  const int outer{static_cast<int>(std::round(std::ceil(scaleFactor * m_thresholds[cls])))};
249  LArCanvasHelper::DrawRing(canvas, row + rowOffset, col + colOffset, inner, outer, 1.f / (outer * outer - inner * inner));
250  }
251  }
252 
253  CartesianPointVector positionVector;
255  canvas, canvasWidth, canvasHeight, colOffset, rowOffset, view, driftMin, driftMax, wireMin[view], wireMax[view], positionVector);
256  if (isU)
257  vertexCandidatesU.emplace_back(positionVector.front());
258  else if (isV)
259  vertexCandidatesV.emplace_back(positionVector.front());
260  else
261  vertexCandidatesW.emplace_back(positionVector.front());
262 
263 #ifdef MONITORING
264  if (m_visualise)
265  {
266  PANDORA_MONITORING_API(SetEveDisplayParameters(this->GetPandora(), true, DETECTOR_VIEW_XZ, -1.f, 1.f, 1.f));
267  const MCParticleList *pMCParticleList{nullptr};
268  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pMCParticleList));
269 
270  CartesianVector trueVertex3D(0, 0, 0);
271  if (LArMCParticleHelper::GetTrueVertex(pMCParticleList, trueVertex3D))
272  {
273  float x{0.f}, u{0.f}, v{0.f}, w{0.f};
274  const LArTransformationPlugin *transform{this->GetPandora().GetPlugins()->GetLArTransformationPlugin()};
275  LArVertexHelper::GetTrueVertexPosition(trueVertex3D, transform, x, u, v, w);
276  if (isU)
277  {
278  const CartesianVector trueVertex(x, 0.f, u);
279  PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &trueVertex, "U(true)", BLUE, 3));
280  }
281  else if (isV)
282  {
283  const CartesianVector trueVertex(x, 0.f, v);
284  PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &trueVertex, "V(true)", BLUE, 3));
285  }
286  else if (isW)
287  {
288  const CartesianVector trueVertex(x, 0.f, w);
289  PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &trueVertex, "W(true)", BLUE, 3));
290  }
291  for (const auto &pos : positionVector)
292  {
293  std::string label{isU ? "U" : isV ? "V" : "W"};
294  PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &pos, label, RED, 3));
295  }
296  }
297  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
298  }
299 #endif
300 
301  for (int row = 0; row < canvasHeight; ++row)
302  delete[] canvas[row];
303  delete[] canvas;
304  }
305 
306  int nEmptyLists{0};
307  if (vertexCandidatesU.empty())
308  ++nEmptyLists;
309  if (vertexCandidatesV.empty())
310  ++nEmptyLists;
311  if (vertexCandidatesW.empty())
312  ++nEmptyLists;
313  std::vector<VertexTuple> vertexTuples;
314  CartesianPointVector candidates3D;
315  if (nEmptyLists == 0)
316  {
317  vertexTuples.emplace_back(VertexTuple(this->GetPandora(), vertexCandidatesU.front(), vertexCandidatesV.front(), vertexCandidatesW.front()));
318  }
319  else if (nEmptyLists == 1)
320  {
321  if (vertexCandidatesU.empty())
322  { // V and W available
323  vertexTuples.emplace_back(VertexTuple(this->GetPandora(), vertexCandidatesV.front(), vertexCandidatesW.front(), TPC_VIEW_V, TPC_VIEW_W));
324  }
325  else if (vertexCandidatesV.empty())
326  { // U and W available
327  vertexTuples.emplace_back(VertexTuple(this->GetPandora(), vertexCandidatesU.front(), vertexCandidatesW.front(), TPC_VIEW_U, TPC_VIEW_W));
328  }
329  else
330  { // U and V available
331  vertexTuples.emplace_back(VertexTuple(this->GetPandora(), vertexCandidatesU.front(), vertexCandidatesV.front(), TPC_VIEW_U, TPC_VIEW_V));
332  }
333  }
334  else
335  { // Not enough views to reconstruct a 3D vertex
336  std::cout << "Insufficient 2D vertices to reconstruct a 3D vertex" << std::endl;
337  return STATUS_CODE_NOT_FOUND;
338  }
339 
340  if (m_visualise)
341  {
342  PANDORA_MONITORING_API(AddMarkerToVisualization(this->GetPandora(), &vertexTuples.front().GetPosition(), "candidate", GREEN, 1));
343  }
344 
345  if (!vertexTuples.empty())
346  {
347  const CartesianVector &vertex{vertexTuples.front().GetPosition()};
348  CartesianPointVector vertexCandidates;
349  vertexCandidates.emplace_back(vertex);
350  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, this->MakeCandidateVertexList(vertexCandidates));
351  }
352  else
353  {
354  std::cout << "Insufficient 2D vertices to reconstruct a 3D vertex" << std::endl;
355  return STATUS_CODE_NOT_FOUND;
356  }
357 
358  if (m_visualise)
359  {
360  PANDORA_MONITORING_API(ViewEvent(this->GetPandora()));
361  }
362 
363  return STATUS_CODE_SUCCESS;
364 }
Float_t x
Definition: compare.C:6
int m_pass
The pass of the train/infer step.
LArDLHelper::TorchModel m_modelU
The model for the U view.
bool m_visualise
Whether or not to visualise the candidate vertices.
int m_event
The current event number.
std::vector< double > m_thresholds
Distance class thresholds.
TFile f
Definition: plotHisto.C:6
static void DrawRing(float **canvas, const int row, const int col, const int inner, const int outer, const float weight)
Add a filled ring to the specified canvas. The ring has an inner radius based on the minimum predicte...
Int_t col[ntarg]
Definition: Style.C:29
pandora::StringVector m_caloHitListNames
Names of input calo hit lists.
std::string m_inputVertexListName
Input vertex list name if 2nd pass.
void GetHitRegion(const pandora::CaloHitList &caloHitList, float &xMin, float &xMax, float &zMin, float &zMax) const
static void Forward(TorchModel &model, const TorchInputVector &input, TorchOutput &output)
Run a deep learning model.
Definition: LArDLHelper.cc:41
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 ...
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_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
HitType
Definition: HitType.h:12
pandora::StatusCode MakeCandidateVertexList(const pandora::CartesianPointVector &positions)
Create a vertex list from the candidate vertices.
int m_nClasses
The number of distance classes.
Float_t w
Definition: plot.C:20
std::list< Vertex > VertexList
Definition: DCEL.h:169
LArDLHelper::TorchModel m_modelV
The model for the V view.
std::vector< torch::jit::IValue > TorchInputVector
Definition: LArDLHelper.h:27
vertex reconstruction
StatusCode lar_dl_content::DlVertexingAlgorithm::MakeCandidateVertexList ( const pandora::CartesianPointVector &  positions)
private

Create a vertex list from the candidate vertices.

Parameters
candidatesThe candidate positions with which to create the list.
Returns
The StatusCode resulting from the function

Definition at line 452 of file DlVertexingAlgorithm.cc.

References m_event, lar_dl_content::DlVertexingBaseAlgorithm::m_outputVertexListName, lar_dl_content::DlVertexingBaseAlgorithm::m_pass, m_rootTreeName, lar_dl_content::DlVertexingBaseAlgorithm::m_volumeType, and m_writeTree.

Referenced by Infer().

453 {
454  const VertexList *pVertexList{nullptr};
455  std::string temporaryListName;
456  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::CreateTemporaryListAndSetCurrent(*this, pVertexList, temporaryListName));
457 
458  for (const CartesianVector &position : positions)
459  {
460  PandoraContentApi::Vertex::Parameters parameters;
461  parameters.m_position = position;
462  parameters.m_vertexLabel = VERTEX_INTERACTION;
463  parameters.m_vertexType = VERTEX_3D;
464 
465  const Vertex *pVertex(nullptr);
466  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::Vertex::Create(*this, parameters, pVertex));
467  }
468  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList<Vertex>(*this, m_outputVertexListName));
469  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::ReplaceCurrentList<Vertex>(*this, m_outputVertexListName));
470 
471  return STATUS_CODE_SUCCESS;
472 }
std::string m_outputVertexListName
Output vertex list name.
boost::graph_traits< ModuleGraph >::vertex_descriptor Vertex
Definition: ModuleGraph.h:25
std::list< Vertex > VertexList
Definition: DCEL.h:169
StatusCode lar_dl_content::DlVertexingAlgorithm::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
private

Definition at line 368 of file DlVertexingAlgorithm.cc.

References util::begin(), col, lar_dl_content::LArDLHelper::InitialiseInput(), lar_dl_content::DlVertexingBaseAlgorithm::m_driftStep, lar_dl_content::DlVertexingBaseAlgorithm::m_height, lar_dl_content::DlVertexingBaseAlgorithm::m_pass, lar_dl_content::DlVertexingBaseAlgorithm::m_width, value, x, and z.

Referenced by Infer().

370 {
371  // ATTN If wire w pitches vary between TPCs, exception will be raised in initialisation of lar pseudolayer plugin
372  const LArTPC *const pTPC(this->GetPandora().GetGeometry()->GetLArTPCMap().begin()->second);
373  const float pitch(view == TPC_VIEW_U ? pTPC->GetWirePitchU() : view == TPC_VIEW_V ? pTPC->GetWirePitchV() : pTPC->GetWirePitchW());
374 
375  // Determine the bin edges
376  std::vector<double> xBinEdges(m_width + 1);
377  std::vector<double> zBinEdges(m_height + 1);
378  xBinEdges[0] = xMin - 0.5f * m_driftStep;
379  const double dx = ((xMax + 0.5f * m_driftStep) - xBinEdges[0]) / m_width;
380  for (int i = 1; i < m_width + 1; ++i)
381  xBinEdges[i] = xBinEdges[i - 1] + dx;
382  zBinEdges[0] = zMin - 0.5f * pitch;
383  const double dz = ((zMax + 0.5f * pitch) - zBinEdges[0]) / m_height;
384  for (int i = 1; i < m_height + 1; ++i)
385  zBinEdges[i] = zBinEdges[i - 1] + dz;
386 
387  LArDLHelper::InitialiseInput({1, 1, m_height, m_width}, networkInput);
388  auto accessor = networkInput.accessor<float, 4>();
389 
390  for (const CaloHit *pCaloHit : caloHits)
391  {
392  const float x{pCaloHit->GetPositionVector().GetX()};
393  const float z{pCaloHit->GetPositionVector().GetZ()};
394  if (m_pass > 1)
395  {
396  if (x < xMin || x > xMax || z < zMin || z > zMax)
397  continue;
398  }
399  const float adc{pCaloHit->GetMipEquivalentEnergy()};
400  const int pixelX{static_cast<int>(std::floor((x - xBinEdges[0]) / dx))};
401  const int pixelZ{static_cast<int>(std::floor((z - zBinEdges[0]) / dz))};
402  accessor[0][0][pixelZ][pixelX] += adc;
403  }
404  for (int row = 0; row < m_height; ++row)
405  {
406  for (int col = 0; col < m_width; ++col)
407  {
408  const float value{accessor[0][0][row][col]};
409  if (value > 0)
410  pixelVector.emplace_back(std::make_pair(row, col));
411  }
412  }
413 
414  return STATUS_CODE_SUCCESS;
415 }
Float_t x
Definition: compare.C:6
int m_pass
The pass of the train/infer step.
Double_t z
Definition: plot.C:276
float m_driftStep
The size of a pixel in the drift direction in cm (most relevant in pass 2)
Int_t col[ntarg]
Definition: Style.C:29
double value
Definition: spectrum.C:18
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:82
static void InitialiseInput(const at::IntArrayRef dimensions, TorchInput &tensor)
Create a torch input tensor.
Definition: LArDLHelper.cc:34
StatusCode lar_dl_content::DlVertexingAlgorithm::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
private

Definition at line 419 of file DlVertexingAlgorithm.cc.

References util::begin(), col, f, lar_dl_content::DlVertexingBaseAlgorithm::m_driftStep, lar_dl_content::DlVertexingBaseAlgorithm::m_height, lar_dl_content::DlVertexingBaseAlgorithm::m_width, pt, x, and z.

Referenced by Infer().

422 {
423  // ATTN If wire w pitches vary between TPCs, exception will be raised in initialisation of lar pseudolayer plugin
424  const LArTPC *const pTPC(this->GetPandora().GetGeometry()->GetLArTPCMap().begin()->second);
425  const float pitch(view == TPC_VIEW_U ? pTPC->GetWirePitchU() : view == TPC_VIEW_V ? pTPC->GetWirePitchV() : pTPC->GetWirePitchW());
426 
427  const double dx = ((xMax + 0.5f * m_driftStep) - (xMin - 0.5f * m_driftStep)) / m_width;
428  const double dz = ((zMax + 0.5f * pitch) - (zMin - 0.5f * pitch)) / m_height;
429 
430  float best{-1.f};
431  int rowBest{0}, colBest{0};
432  for (int row = 0; row < canvasHeight; ++row)
433  for (int col = 0; col < canvasWidth; ++col)
434  if (canvas[row][col] > 0 && canvas[row][col] > best)
435  {
436  best = canvas[row][col];
437  rowBest = row;
438  colBest = col;
439  }
440 
441  const float x{static_cast<float>((colBest - columnOffset) * dx + xMin)};
442  const float z{static_cast<float>((rowBest - rowOffset) * dz + zMin)};
443 
444  CartesianVector pt(x, 0.f, z);
445  positionVector.emplace_back(pt);
446 
447  return STATUS_CODE_SUCCESS;
448 }
Float_t x
Definition: compare.C:6
Double_t z
Definition: plot.C:276
float m_driftStep
The size of a pixel in the drift direction in cm (most relevant in pass 2)
TFile f
Definition: plotHisto.C:6
Int_t col[ntarg]
Definition: Style.C:29
TMarker * pt
Definition: egs.C:25
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
second_as<> second
Type of time stored in seconds, in double precision.
Definition: spacetime.h:82
StatusCode lar_dl_content::DlVertexingAlgorithm::PrepareTrainingSample ( )
private

Definition at line 65 of file DlVertexingAlgorithm.cc.

References f, lar_dl_content::DlVertexingBaseAlgorithm::GetHitRegion(), lar_dl_content::DlVertexingBaseAlgorithm::m_caloHitListNames, lar_dl_content::DlVertexingBaseAlgorithm::m_pass, lar_dl_content::DlVertexingBaseAlgorithm::m_trainingOutputFile, x, and z.

Referenced by Run().

66 {
67  const CaloHitList *pCaloHitList2D(nullptr);
68  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, "CaloHitList2D", pCaloHitList2D));
69  const MCParticleList *pMCParticleList(nullptr);
70  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetCurrentList(*this, pMCParticleList));
72  LArMCParticleHelper::GetMCToHitsMap(pCaloHitList2D, pMCParticleList, mcToHitsMap);
73  MCParticleList hierarchy;
74  LArMCParticleHelper::CompleteMCHierarchy(mcToHitsMap, hierarchy);
75 
76  // Get boundaries for hits and make x dimension common
77  std::map<HitType, float> wireMin, wireMax;
78  float driftMin{std::numeric_limits<float>::max()}, driftMax{-std::numeric_limits<float>::max()};
79  for (const std::string &listname : m_caloHitListNames)
80  {
81  const CaloHitList *pCaloHitList{nullptr};
82  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, listname, pCaloHitList));
83  if (pCaloHitList->empty())
84  continue;
85 
86  HitType view{pCaloHitList->front()->GetHitType()};
87  float viewDriftMin{driftMin}, viewDriftMax{driftMax};
88  this->GetHitRegion(*pCaloHitList, viewDriftMin, viewDriftMax, wireMin[view], wireMax[view]);
89  driftMin = std::min(viewDriftMin, driftMin);
90  driftMax = std::max(viewDriftMax, driftMax);
91  }
92  for (const std::string &listname : m_caloHitListNames)
93  {
94  const CaloHitList *pCaloHitList(nullptr);
95  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, listname, pCaloHitList));
96  if (pCaloHitList->empty())
97  continue;
98 
99  HitType view{pCaloHitList->front()->GetHitType()};
100  const bool isU{view == TPC_VIEW_U}, isV{view == TPC_VIEW_V}, isW{view == TPC_VIEW_W};
101  if (!(isU || isV || isW))
102  return STATUS_CODE_NOT_ALLOWED;
103 
104  CartesianPointVector vertices;
105  for (const MCParticle *mc : hierarchy)
106  {
107  if (LArMCParticleHelper::IsNeutrino(mc))
108  vertices.push_back(mc->GetVertex());
109  }
110  if (vertices.empty())
111  continue;
112  const CartesianVector &vertex{vertices.front()};
113  const std::string trainingFilename{m_trainingOutputFile + "_" + listname + ".csv"};
114  const unsigned long nVertices{1};
115  unsigned long nHits{0};
116  const unsigned int nuance{LArMCParticleHelper::GetNuanceCode(hierarchy.front())};
117 
118  // Vertices
119  const LArTransformationPlugin *transform{this->GetPandora().GetPlugins()->GetLArTransformationPlugin()};
120  const double xVtx{vertex.GetX()};
121  double zVtx{0.};
122  if (isW)
123  zVtx = transform->YZtoW(vertex.GetY(), vertex.GetZ());
124  else if (isV)
125  zVtx = transform->YZtoV(vertex.GetY(), vertex.GetZ());
126  else
127  zVtx = transform->YZtoU(vertex.GetY(), vertex.GetZ());
128 
129  // Calo hits
130  double xMin{driftMin}, xMax{driftMax}, zMin{wireMin[view]}, zMax{wireMax[view]};
131 
132  // Only train on events where the vertex resides within the image - with a small tolerance
133  if (!(xVtx > (xMin - 1.f) && xVtx < (xMax + 1.f) && zVtx > (zMin - 1.f) && zVtx < (zMax + 1.f)))
134  continue;
135 
136  LArMvaHelper::MvaFeatureVector featureVector;
137  featureVector.emplace_back(static_cast<double>(nuance));
138  featureVector.emplace_back(static_cast<double>(nVertices));
139  featureVector.emplace_back(xVtx);
140  featureVector.emplace_back(zVtx);
141  // Retain the hit region
142  featureVector.emplace_back(xMin);
143  featureVector.emplace_back(xMax);
144  featureVector.emplace_back(zMin);
145  featureVector.emplace_back(zMax);
146 
147  for (const CaloHit *pCaloHit : *pCaloHitList)
148  {
149  const float x{pCaloHit->GetPositionVector().GetX()}, z{pCaloHit->GetPositionVector().GetZ()}, adc{pCaloHit->GetMipEquivalentEnergy()};
150  // If on a refinement pass, drop hits outside the region of interest
151  if (m_pass > 1 && (x < xMin || x > xMax || z < zMin || z > zMax))
152  continue;
153  featureVector.emplace_back(static_cast<double>(x));
154  featureVector.emplace_back(static_cast<double>(z));
155  featureVector.emplace_back(static_cast<double>(adc));
156  ++nHits;
157  }
158  featureVector.insert(featureVector.begin() + 8, static_cast<double>(nHits));
159  // Only write out the feature vector if there were enough hits in the region of interest
160  if (nHits > 10)
161  LArMvaHelper::ProduceTrainingExample(trainingFilename, true, featureVector);
162  }
163 
164  return STATUS_CODE_SUCCESS;
165 }
Float_t x
Definition: compare.C:6
int m_pass
The pass of the train/infer step.
std::unordered_map< const pandora::MCParticle *, pandora::CaloHitList > MCContributionMap
MvaTypes::MvaFeatureVector MvaFeatureVector
Definition: LArMvaHelper.h:75
Double_t z
Definition: plot.C:276
std::string m_trainingOutputFile
Output file name for training examples.
TFile f
Definition: plotHisto.C:6
pandora::StringVector m_caloHitListNames
Names of input calo hit lists.
void GetHitRegion(const pandora::CaloHitList &caloHitList, float &xMin, float &xMax, float &zMin, float &zMax) const
HitType
Definition: HitType.h:12
vertex reconstruction
StatusCode lar_dl_content::DlVertexingAlgorithm::ReadSettings ( const pandora::TiXmlHandle  xmlHandle)
private

Definition at line 540 of file DlVertexingAlgorithm.cc.

References m_rootFileName, m_rootTreeName, lar_dl_content::DlVertexingBaseAlgorithm::m_trainingMode, m_visualise, m_writeTree, and lar_dl_content::DlVertexingBaseAlgorithm::ReadSettings().

541 {
542  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, DlVertexingBaseAlgorithm::ReadSettings(xmlHandle));
543 
544  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "Visualise", m_visualise));
545 
546  if (!m_trainingMode)
547  {
548  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "WriteTree", m_writeTree));
549  if (m_writeTree)
550  {
551  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RootTreeName", m_rootTreeName));
552  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle, "RootFileName", m_rootFileName));
553  }
554  }
555 
556  return STATUS_CODE_SUCCESS;
557 }
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
bool m_visualise
Whether or not to visualise the candidate vertices.
std::string m_rootTreeName
The ROOT tree name.
bool m_writeTree
Whether or not to write validation details to a ROOT tree.
std::string m_rootFileName
The ROOT file name.
StatusCode lar_dl_content::DlVertexingAlgorithm::Run ( )
private

Definition at line 55 of file DlVertexingAlgorithm.cc.

References Infer(), lar_dl_content::DlVertexingBaseAlgorithm::m_trainingMode, and PrepareTrainingSample().

56 {
57  if (m_trainingMode)
58  return this->PrepareTrainingSample();
59  else
60  return this->Infer();
61 
62  return STATUS_CODE_SUCCESS;
63 }

Member Data Documentation

float lar_dl_content::DlVertexingBaseAlgorithm::m_driftStep
protectedinherited
int lar_dl_content::DlVertexingAlgorithm::m_event
private

The current event number.

Definition at line 99 of file DlVertexingAlgorithm.h.

Referenced by Infer(), and MakeCandidateVertexList().

std::string lar_dl_content::DlVertexingBaseAlgorithm::m_inputVertexListName
protectedinherited
LArDLHelper::TorchModel lar_dl_content::DlVertexingBaseAlgorithm::m_modelU
protectedinherited
LArDLHelper::TorchModel lar_dl_content::DlVertexingBaseAlgorithm::m_modelV
protectedinherited
LArDLHelper::TorchModel lar_dl_content::DlVertexingBaseAlgorithm::m_modelW
protectedinherited
int lar_dl_content::DlVertexingBaseAlgorithm::m_nClasses
protectedinherited
std::string lar_dl_content::DlVertexingBaseAlgorithm::m_outputVertexListName
protectedinherited
std::mt19937 lar_dl_content::DlVertexingAlgorithm::m_rng
private

The random number generator.

Definition at line 104 of file DlVertexingAlgorithm.h.

Referenced by DlVertexingAlgorithm().

std::string lar_dl_content::DlVertexingAlgorithm::m_rootFileName
private

The ROOT file name.

Definition at line 103 of file DlVertexingAlgorithm.h.

Referenced by ReadSettings(), and ~DlVertexingAlgorithm().

std::string lar_dl_content::DlVertexingAlgorithm::m_rootTreeName
private

The ROOT tree name.

Definition at line 102 of file DlVertexingAlgorithm.h.

Referenced by MakeCandidateVertexList(), ReadSettings(), and ~DlVertexingAlgorithm().

std::vector<double> lar_dl_content::DlVertexingBaseAlgorithm::m_thresholds
protectedinherited
bool lar_dl_content::DlVertexingBaseAlgorithm::m_trainingMode
protectedinherited
std::string lar_dl_content::DlVertexingBaseAlgorithm::m_trainingOutputFile
protectedinherited
bool lar_dl_content::DlVertexingAlgorithm::m_visualise
private

Whether or not to visualise the candidate vertices.

Definition at line 100 of file DlVertexingAlgorithm.h.

Referenced by DlVertexingAlgorithm(), Infer(), and ReadSettings().

std::string lar_dl_content::DlVertexingBaseAlgorithm::m_volumeType
protectedinherited
bool lar_dl_content::DlVertexingAlgorithm::m_writeTree
private

Whether or not to write validation details to a ROOT tree.

Definition at line 101 of file DlVertexingAlgorithm.h.

Referenced by DlVertexingAlgorithm(), MakeCandidateVertexList(), ReadSettings(), and ~DlVertexingAlgorithm().


The documentation for this class was generated from the following files: