LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
ProtoShowerMatchingTool.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 #include "Pandora/AlgorithmTool.h"
11 
14 
16 
19 
20 using namespace pandora;
21 
22 namespace lar_content
23 {
24 
25 ProtoShowerMatchingTool::ProtoShowerMatchingTool() :
26  m_spineSlidingFitWindow(20),
27  m_maxXSeparation(5.f),
28  m_maxSeparation(5.f),
29  m_maxAngularDeviation(5.f)
30 {
31 }
32 
33 //------------------------------------------------------------------------------------------------------------------------------------------
34 
35 StatusCode ProtoShowerMatchingTool::Run(const ProtoShowerVector &protoShowerVectorU, const ProtoShowerVector &protoShowerVectorV,
36  const ProtoShowerVector &protoShowerVectorW, ProtoShowerMatchVector &protoShowerMatchVector)
37 {
38  IntVector usedProtoShowersU, usedProtoShowersV, usedProtoShowersW;
39 
40  bool added(false);
41 
42  for (unsigned int uIndex = 0; uIndex < protoShowerVectorU.size(); ++uIndex)
43  {
44  added = false;
45 
46  if (std::find(usedProtoShowersU.begin(), usedProtoShowersU.end(), uIndex) != usedProtoShowersU.end())
47  continue;
48 
49  const ProtoShower &protoShowerU(protoShowerVectorU.at(uIndex));
50 
51  for (unsigned int vIndex = 0; vIndex < protoShowerVectorV.size(); ++vIndex)
52  {
53  if (std::find(usedProtoShowersV.begin(), usedProtoShowersV.end(), vIndex) != usedProtoShowersV.end())
54  continue;
55 
56  const ProtoShower &protoShowerV(protoShowerVectorV.at(vIndex));
57 
58  for (unsigned int wIndex = 0; wIndex < protoShowerVectorW.size(); ++wIndex)
59  {
60  if (std::find(usedProtoShowersW.begin(), usedProtoShowersW.end(), wIndex) != usedProtoShowersW.end())
61  continue;
62 
63  const ProtoShower &protoShowerW(protoShowerVectorW.at(wIndex));
65 
66  if (!this->ArePathwaysConsistent(protoShowerU, protoShowerV, protoShowerW, consistency))
67  continue;
68 
69  usedProtoShowersU.push_back(uIndex);
70  usedProtoShowersV.push_back(vIndex);
71  usedProtoShowersW.push_back(wIndex);
72 
73  protoShowerMatchVector.push_back(ProtoShowerMatch(protoShowerU, protoShowerV, protoShowerW, consistency));
74 
75  added = true;
76  break;
77  }
78 
79  if (added)
80  break;
81  }
82  }
83 
84  return STATUS_CODE_SUCCESS;
85 }
86 
87 //------------------------------------------------------------------------------------------------------------------------------------------
88 
90  const ProtoShower &protoShowerU, const ProtoShower &protoShowerV, const ProtoShower &protoShowerW, Consistency &consistency) const
91 {
92  if (this->AreShowerStartsConsistent(protoShowerU, protoShowerV, protoShowerW))
93  {
94  consistency = Consistency::POSITION;
95  }
96  else if (this->AreDirectionsConsistent(protoShowerU, protoShowerV, protoShowerW))
97  {
98  consistency = Consistency::DIRECTION;
99  }
100  else
101  {
102  return false;
103  }
104 
105  return true;
106 }
107 
108 //------------------------------------------------------------------------------------------------------------------------------------------
109 
110 bool ProtoShowerMatchingTool::AreShowerStartsConsistent(const ProtoShower &protoShowerU, const ProtoShower &protoShowerV, const ProtoShower &protoShowerW) const
111 {
112  const CartesianVector &showerStartU(protoShowerU.GetShowerCore().GetStartPosition());
113  const CartesianVector &showerStartV(protoShowerV.GetShowerCore().GetStartPosition());
114  const CartesianVector &showerStartW(protoShowerW.GetShowerCore().GetStartPosition());
115 
116  const float xSeparationUV(std::fabs(showerStartU.GetX() - showerStartV.GetX()));
117  const float xSeparationUW(std::fabs(showerStartU.GetX() - showerStartW.GetX()));
118  const float xSeparationVW(std::fabs(showerStartV.GetX() - showerStartW.GetX()));
119 
120  if ((xSeparationUV > m_maxXSeparation) || (xSeparationUW > m_maxXSeparation) || (xSeparationVW > m_maxXSeparation))
121  return false;
122 
123  float chi2(0.f);
124  CartesianVector projectionU(0.f, 0.f, 0.f), projectionV(0.f, 0.f, 0.f), projectionW(0.f, 0.f, 0.f);
125 
126  LArGeometryHelper::MergeTwoPositions(this->GetPandora(), TPC_VIEW_V, TPC_VIEW_W, showerStartV, showerStartW, projectionU, chi2);
127  LArGeometryHelper::MergeTwoPositions(this->GetPandora(), TPC_VIEW_W, TPC_VIEW_U, showerStartW, showerStartU, projectionV, chi2);
128  LArGeometryHelper::MergeTwoPositions(this->GetPandora(), TPC_VIEW_U, TPC_VIEW_V, showerStartU, showerStartV, projectionW, chi2);
129 
130  const float separationU((projectionU - showerStartU).GetMagnitude());
131  const float separationV((projectionV - showerStartV).GetMagnitude());
132  const float separationW((projectionW - showerStartW).GetMagnitude());
133 
134  const float metric((separationU + separationV + separationW) / 3.f);
135 
136  return (metric < m_maxSeparation);
137 }
138 
139 //------------------------------------------------------------------------------------------------------------------------------------------
140 
141 bool ProtoShowerMatchingTool::AreDirectionsConsistent(const ProtoShower &protoShowerU, const ProtoShower &protoShowerV, const ProtoShower &protoShowerW) const
142 {
143  const CartesianVector &directionU1(protoShowerU.GetConnectionPathway().GetStartDirection());
144  const CartesianVector &directionV1(protoShowerV.GetConnectionPathway().GetStartDirection());
145  const CartesianVector &directionW1(protoShowerW.GetConnectionPathway().GetStartDirection());
146 
147  if (this->AreDirectionsConsistent(directionU1, directionV1, directionW1))
148  {
149  return true;
150  }
151  else
152  {
153  const bool isDownstream(
154  protoShowerW.GetShowerCore().GetStartPosition().GetZ() > protoShowerW.GetConnectionPathway().GetStartPosition().GetZ());
155 
156  CartesianPointVector spinePositionsU, spinePositionsV, spinePositionsW;
157 
158  for (const CaloHit *const pCaloHit : protoShowerU.GetSpineHitList())
159  spinePositionsU.push_back(pCaloHit->GetPositionVector());
160 
161  for (const CaloHit *const pCaloHit : protoShowerV.GetSpineHitList())
162  spinePositionsV.push_back(pCaloHit->GetPositionVector());
163 
164  for (const CaloHit *const pCaloHit : protoShowerW.GetSpineHitList())
165  spinePositionsW.push_back(pCaloHit->GetPositionVector());
166 
167  const TwoDSlidingFitResult spineFitU(&spinePositionsU, m_spineSlidingFitWindow, LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_U));
168  const TwoDSlidingFitResult spineFitV(&spinePositionsV, m_spineSlidingFitWindow, LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_V));
169  const TwoDSlidingFitResult spineFitW(&spinePositionsW, m_spineSlidingFitWindow, LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_W));
170 
171  const CartesianVector directionU2(isDownstream ? spineFitU.GetGlobalMinLayerDirection() : spineFitU.GetGlobalMaxLayerDirection() * (-1.f));
172  const CartesianVector directionV2(isDownstream ? spineFitV.GetGlobalMinLayerDirection() : spineFitV.GetGlobalMaxLayerDirection() * (-1.f));
173  const CartesianVector directionW2(isDownstream ? spineFitW.GetGlobalMinLayerDirection() : spineFitW.GetGlobalMaxLayerDirection() * (-1.f));
174 
175  return this->AreDirectionsConsistent(directionU2, directionV2, directionW2);
176  }
177 
178  return false;
179 }
180 
181 //------------------------------------------------------------------------------------------------------------------------------------------
182 
183 bool ProtoShowerMatchingTool::AreDirectionsConsistent(CartesianVector directionU, CartesianVector directionV, CartesianVector directionW) const
184 {
185  const CartesianVector wireAxis(0.f, 0.f, 1.f);
186 
187  float wireDeviationU(directionU.GetOpeningAngle(wireAxis));
188  wireDeviationU = std::min(wireDeviationU, static_cast<float>(M_PI - wireDeviationU));
189 
190  float wireDeviationV(directionV.GetOpeningAngle(wireAxis));
191  wireDeviationV = std::min(wireDeviationV, static_cast<float>(M_PI - wireDeviationV));
192 
193  float wireDeviationW(directionW.GetOpeningAngle(wireAxis));
194  wireDeviationW = std::min(wireDeviationW, static_cast<float>(M_PI - wireDeviationW));
195 
196  float radians((2.f * M_PI) / 180.f);
197  bool isIsochronous((wireDeviationU < radians) && (wireDeviationV < radians) && (wireDeviationW < radians));
198 
199  if (isIsochronous)
200  {
201  // Enforce consistency
202  directionU = CartesianVector(std::fabs(directionU.GetX()), 0.f, directionU.GetZ());
203  directionV = CartesianVector(std::fabs(directionV.GetX()), 0.f, directionV.GetZ());
204  directionW = CartesianVector(std::fabs(directionW.GetX()), 0.f, directionW.GetZ());
205  }
206 
207  if (directionU.GetX() * directionV.GetX() < 0.f)
208  return false;
209 
210  if (directionU.GetX() * directionW.GetX() < 0.f)
211  return false;
212 
213  if (directionV.GetX() * directionW.GetX() < 0.f)
214  return false;
215 
216  const CartesianVector projectionU(LArGeometryHelper::MergeTwoDirections(this->GetPandora(), TPC_VIEW_V, TPC_VIEW_W, directionV, directionW));
217  const CartesianVector projectionV(LArGeometryHelper::MergeTwoDirections(this->GetPandora(), TPC_VIEW_W, TPC_VIEW_U, directionW, directionU));
218  const CartesianVector projectionW(LArGeometryHelper::MergeTwoDirections(this->GetPandora(), TPC_VIEW_U, TPC_VIEW_V, directionU, directionV));
219 
220  float openingAngleU(directionU.GetOpeningAngle(projectionU) * 180.f / M_PI);
221  float openingAngleV(directionV.GetOpeningAngle(projectionV) * 180.f / M_PI);
222  float openingAngleW(directionW.GetOpeningAngle(projectionW) * 180.f / M_PI);
223 
224  if (isIsochronous)
225  {
226  openingAngleU = std::min(openingAngleU, 180.f - openingAngleU);
227  openingAngleV = std::min(openingAngleV, 180.f - openingAngleV);
228  openingAngleW = std::min(openingAngleW, 180.f - openingAngleW);
229  }
230 
231  if ((openingAngleU > m_maxAngularDeviation) || (openingAngleV > m_maxAngularDeviation) || (openingAngleW > m_maxAngularDeviation))
232  return false;
233 
234  return true;
235 }
236 
237 //------------------------------------------------------------------------------------------------------------------------------------------
238 
239 StatusCode ProtoShowerMatchingTool::ReadSettings(const TiXmlHandle xmlHandle)
240 {
241  PANDORA_RETURN_RESULT_IF_AND_IF(
242  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SpineSlidingFitWindow", m_spineSlidingFitWindow));
243 
244  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxXSeparation", m_maxXSeparation));
245 
246  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxSeparation", m_maxSeparation));
247 
248  PANDORA_RETURN_RESULT_IF_AND_IF(
249  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxAngularDeviation", m_maxAngularDeviation));
250 
251  return STATUS_CODE_SUCCESS;
252 }
253 
254 } // namespace lar_content
Header file for the ProtoShower class.
Header file for the connection pathway helper class.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
Consistency
Consistency enumeration.
static pandora::CartesianVector MergeTwoDirections(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const pandora::CartesianVector &direction1, const pandora::CartesianVector &direction2)
Merge two views (U,V) to give a third view (Z).
const ConnectionPathway & GetConnectionPathway() const
Get the connection pathway.
pandora::StatusCode Run(const ProtoShowerVector &protoShowerVectorU, const ProtoShowerVector &protoShowerVectorV, const ProtoShowerVector &protoShowerVectorW, ProtoShowerMatchVector &protoShowerMatchVector)
bool AreDirectionsConsistent(const ProtoShower &protoShowerU, const ProtoShower &protoShowerV, const ProtoShower &protoShowerW) const
Determine whether three 2D initial spine directions correspond to the same 3D initial spine direction...
std::vector< int > IntVector
float m_maxXSeparation
The max. drift-coordinate separation between matched 2D shower start positions.
pandora::CartesianVector GetGlobalMinLayerDirection() const
Get global direction corresponding to the fit result in minimum fit layer.
const pandora::CaloHitList & GetSpineHitList() const
Get the spine hit list.
ProtoShowerMatch class.
TFile f
Definition: plotHisto.C:6
const pandora::CartesianVector & GetStartPosition() const
Get the start position of the connection pathway.
Header file for the geometry helper class.
unsigned int m_spineSlidingFitWindow
The shower spine sliding fit window.
bool AreShowerStartsConsistent(const ProtoShower &protoShowerU, const ProtoShower &protoShowerV, const ProtoShower &protoShowerW) const
Determine whether three 2D shower start positions correspond to the same 3D shower start position...
const pandora::CartesianVector & GetStartPosition() const
Get the start position of the shower core.
Header file for the lar two dimensional sliding fit result class.
static float MergeTwoPositions(const pandora::Pandora &pandora, const pandora::HitType view1, const pandora::HitType view2, const float position1, const float position2)
Merge two views (U,V) to give a third view (Z).
static float GetWirePitch(const pandora::Pandora &pandora, const pandora::HitType view, const float maxWirePitchDiscrepancy=0.01)
Return the wire pitch.
float m_maxAngularDeviation
The max. opening angle between true and projected 2D initial directions for a match.
ProtoShower class.
Header file for the ProtoShower matching tool class.
float m_maxSeparation
The max. average separation between true and projected 2D shower start positions for a match...
std::vector< ProtoShowerMatch > ProtoShowerMatchVector
std::vector< ProtoShower > ProtoShowerVector
pandora::CartesianVector GetGlobalMaxLayerDirection() const
Get global direction corresponding to the fit result in maximum fit layer.
const ShowerCore & GetShowerCore() const
Get the shower core.
bool ArePathwaysConsistent(const ProtoShower &protoShowerU, const ProtoShower &protoShowerV, const ProtoShower &protoShowerW, Consistency &consistency) const
Determine whether three 2D connection pathways form a consistent 3D connection pathway.
const pandora::CartesianVector & GetStartDirection() const
Get the start direction of the connection pathway.