LArSoft  v10_04_05
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_xExtrapolation(5.f),
30  m_maxAngularDeviation(5.f)
31 {
32 }
33 
34 //------------------------------------------------------------------------------------------------------------------------------------------
35 
36 StatusCode ProtoShowerMatchingTool::Run(const ProtoShowerVector &protoShowerVectorU, const ProtoShowerVector &protoShowerVectorV,
37  const ProtoShowerVector &protoShowerVectorW, ProtoShowerMatchVector &protoShowerMatchVector)
38 {
39  IntVector usedProtoShowersU, usedProtoShowersV, usedProtoShowersW;
40 
41  bool added(false);
42 
43  for (unsigned int uIndex = 0; uIndex < protoShowerVectorU.size(); ++uIndex)
44  {
45  added = false;
46 
47  if (std::find(usedProtoShowersU.begin(), usedProtoShowersU.end(), uIndex) != usedProtoShowersU.end())
48  continue;
49 
50  const ProtoShower &protoShowerU(protoShowerVectorU.at(uIndex));
51 
52  for (unsigned int vIndex = 0; vIndex < protoShowerVectorV.size(); ++vIndex)
53  {
54  if (std::find(usedProtoShowersV.begin(), usedProtoShowersV.end(), vIndex) != usedProtoShowersV.end())
55  continue;
56 
57  const ProtoShower &protoShowerV(protoShowerVectorV.at(vIndex));
58 
59  for (unsigned int wIndex = 0; wIndex < protoShowerVectorW.size(); ++wIndex)
60  {
61  if (std::find(usedProtoShowersW.begin(), usedProtoShowersW.end(), wIndex) != usedProtoShowersW.end())
62  continue;
63 
64  const ProtoShower &protoShowerW(protoShowerVectorW.at(wIndex));
66 
67  if (!this->ArePathwaysConsistent(protoShowerU, protoShowerV, protoShowerW, consistency))
68  continue;
69 
70  usedProtoShowersU.push_back(uIndex);
71  usedProtoShowersV.push_back(vIndex);
72  usedProtoShowersW.push_back(wIndex);
73 
74  protoShowerMatchVector.push_back(ProtoShowerMatch(protoShowerU, protoShowerV, protoShowerW, consistency));
75 
76  added = true;
77  break;
78  }
79 
80  if (added)
81  break;
82  }
83  }
84 
85  return STATUS_CODE_SUCCESS;
86 }
87 
88 //------------------------------------------------------------------------------------------------------------------------------------------
89 
91  const ProtoShower &protoShowerU, const ProtoShower &protoShowerV, const ProtoShower &protoShowerW, Consistency &consistency) const
92 {
93  if (this->AreShowerStartsConsistent(protoShowerU, protoShowerV, protoShowerW))
94  {
95  consistency = Consistency::POSITION;
96  }
97  else if (this->AreDirectionsConsistent(protoShowerU, protoShowerV, protoShowerW))
98  {
99  consistency = Consistency::DIRECTION;
100  }
101  else
102  {
103  return false;
104  }
105 
106  return true;
107 }
108 
109 //------------------------------------------------------------------------------------------------------------------------------------------
110 
111 bool ProtoShowerMatchingTool::AreShowerStartsConsistent(const ProtoShower &protoShowerU, const ProtoShower &protoShowerV, const ProtoShower &protoShowerW) const
112 {
113  const CartesianVector &showerStartU(protoShowerU.GetShowerCore().GetStartPosition());
114  const CartesianVector &showerStartV(protoShowerV.GetShowerCore().GetStartPosition());
115  const CartesianVector &showerStartW(protoShowerW.GetShowerCore().GetStartPosition());
116 
117  const float xSeparationUV(std::fabs(showerStartU.GetX() - showerStartV.GetX()));
118  const float xSeparationUW(std::fabs(showerStartU.GetX() - showerStartW.GetX()));
119  const float xSeparationVW(std::fabs(showerStartV.GetX() - showerStartW.GetX()));
120 
121  if ((xSeparationUV > m_maxXSeparation) || (xSeparationUW > m_maxXSeparation) || (xSeparationVW > m_maxXSeparation))
122  return false;
123 
124  float chi2(0.f);
125  CartesianVector projectionU(0.f, 0.f, 0.f), projectionV(0.f, 0.f, 0.f), projectionW(0.f, 0.f, 0.f);
126 
127  LArGeometryHelper::MergeTwoPositions(this->GetPandora(), TPC_VIEW_V, TPC_VIEW_W, showerStartV, showerStartW, projectionU, chi2);
128  LArGeometryHelper::MergeTwoPositions(this->GetPandora(), TPC_VIEW_W, TPC_VIEW_U, showerStartW, showerStartU, projectionV, chi2);
129  LArGeometryHelper::MergeTwoPositions(this->GetPandora(), TPC_VIEW_U, TPC_VIEW_V, showerStartU, showerStartV, projectionW, chi2);
130 
131  const float separationU((projectionU - showerStartU).GetMagnitude());
132  const float separationV((projectionV - showerStartV).GetMagnitude());
133  const float separationW((projectionW - showerStartW).GetMagnitude());
134 
135  const float metric((separationU + separationV + separationW) / 3.f);
136 
137  return (metric < m_maxSeparation);
138 }
139 
140 //------------------------------------------------------------------------------------------------------------------------------------------
141 
142 bool ProtoShowerMatchingTool::AreDirectionsConsistent(const ProtoShower &protoShowerU, const ProtoShower &protoShowerV, const ProtoShower &protoShowerW) const
143 {
144  const CartesianVector &directionU1(protoShowerU.GetConnectionPathway().GetStartDirection());
145  const CartesianVector &directionV1(protoShowerV.GetConnectionPathway().GetStartDirection());
146  const CartesianVector &directionW1(protoShowerW.GetConnectionPathway().GetStartDirection());
147 
149  protoShowerW.GetConnectionPathway().GetStartPosition(), directionU1, directionV1, directionW1))
150  {
151  return true;
152  }
153  else
154  {
155  const bool isDownstream(
156  protoShowerW.GetShowerCore().GetStartPosition().GetZ() > protoShowerW.GetConnectionPathway().GetStartPosition().GetZ());
157 
158  CartesianPointVector spinePositionsU, spinePositionsV, spinePositionsW;
159 
160  for (const CaloHit *const pCaloHit : protoShowerU.GetSpineHitList())
161  spinePositionsU.push_back(pCaloHit->GetPositionVector());
162 
163  for (const CaloHit *const pCaloHit : protoShowerV.GetSpineHitList())
164  spinePositionsV.push_back(pCaloHit->GetPositionVector());
165 
166  for (const CaloHit *const pCaloHit : protoShowerW.GetSpineHitList())
167  spinePositionsW.push_back(pCaloHit->GetPositionVector());
168 
169  const TwoDSlidingFitResult spineFitU(&spinePositionsU, m_spineSlidingFitWindow, LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_U));
170  const TwoDSlidingFitResult spineFitV(&spinePositionsV, m_spineSlidingFitWindow, LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_V));
171  const TwoDSlidingFitResult spineFitW(&spinePositionsW, m_spineSlidingFitWindow, LArGeometryHelper::GetWirePitch(this->GetPandora(), TPC_VIEW_W));
172 
173  const CartesianVector directionU2(isDownstream ? spineFitU.GetGlobalMinLayerDirection() : spineFitU.GetGlobalMaxLayerDirection() * (-1.f));
174  const CartesianVector directionV2(isDownstream ? spineFitV.GetGlobalMinLayerDirection() : spineFitV.GetGlobalMaxLayerDirection() * (-1.f));
175  const CartesianVector directionW2(isDownstream ? spineFitW.GetGlobalMinLayerDirection() : spineFitW.GetGlobalMaxLayerDirection() * (-1.f));
176 
177  return this->AreDirectionsConsistent(protoShowerU.GetConnectionPathway().GetStartPosition(),
178  protoShowerV.GetConnectionPathway().GetStartPosition(), protoShowerW.GetConnectionPathway().GetStartPosition(), directionU2,
179  directionV2, directionW2);
180  }
181 
182  return false;
183 }
184 
185 //------------------------------------------------------------------------------------------------------------------------------------------
186 
187 bool ProtoShowerMatchingTool::AreDirectionsConsistent(const CartesianVector &nuVertexU, const CartesianVector &nuVertexV,
188  const CartesianVector &nuVertexW, const CartesianVector &directionU, const CartesianVector &directionV, const CartesianVector &directionW) const
189 {
190  const CartesianVector wireAxis(0.f, 0.f, 1.f);
191 
192  float wireDeviationU(directionU.GetOpeningAngle(wireAxis));
193  wireDeviationU = std::min(wireDeviationU, static_cast<float>(M_PI - wireDeviationU));
194 
195  float wireDeviationV(directionV.GetOpeningAngle(wireAxis));
196  wireDeviationV = std::min(wireDeviationV, static_cast<float>(M_PI - wireDeviationV));
197 
198  float wireDeviationW(directionW.GetOpeningAngle(wireAxis));
199  wireDeviationW = std::min(wireDeviationW, static_cast<float>(M_PI - wireDeviationW));
200 
201  float radians((2.f * M_PI) / 180.f);
202  bool isIsochronous((wireDeviationU < radians) && (wireDeviationV < radians) && (wireDeviationW < radians));
203 
204  if (isIsochronous)
205  return true;
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 xAxis(1.f, 0.f, 0.f);
217  const float cosOpeningAngleU(std::fabs(directionU.GetCosOpeningAngle(xAxis)));
218  const float cosOpeningAngleV(std::fabs(directionV.GetCosOpeningAngle(xAxis)));
219  const float cosOpeningAngleW(std::fabs(directionW.GetCosOpeningAngle(xAxis)));
220  const CartesianVector uPoint(nuVertexU + (directionU * (m_xExtrapolation / cosOpeningAngleU)));
221  const CartesianVector vPoint(nuVertexV + (directionV * (m_xExtrapolation / cosOpeningAngleV)));
222  const CartesianVector wPoint(nuVertexW + (directionW * (m_xExtrapolation / cosOpeningAngleW)));
223 
224  float chiSquared(0.f);
225 
226  CartesianVector projectionPointU(0.f, 0.f, 0.f);
227  LArGeometryHelper::MergeTwoPositions(this->GetPandora(), TPC_VIEW_V, TPC_VIEW_W, vPoint, wPoint, projectionPointU, chiSquared);
228 
229  CartesianVector projectionPointV(0.f, 0.f, 0.f);
230  LArGeometryHelper::MergeTwoPositions(this->GetPandora(), TPC_VIEW_W, TPC_VIEW_U, wPoint, uPoint, projectionPointV, chiSquared);
231 
232  CartesianVector projectionPointW(0.f, 0.f, 0.f);
233  LArGeometryHelper::MergeTwoPositions(this->GetPandora(), TPC_VIEW_U, TPC_VIEW_V, uPoint, vPoint, projectionPointW, chiSquared);
234 
235  // Project U
236  const CartesianVector projectionU((projectionPointU - nuVertexU).GetUnitVector());
237 
238  // Project V
239  const CartesianVector projectionV((projectionPointV - nuVertexV).GetUnitVector());
240 
241  // Project W
242  const CartesianVector projectionW((projectionPointW - nuVertexW).GetUnitVector());
243 
244  float openingAngleU(directionU.GetOpeningAngle(projectionU) * 180.f / M_PI);
245  float openingAngleV(directionV.GetOpeningAngle(projectionV) * 180.f / M_PI);
246  float openingAngleW(directionW.GetOpeningAngle(projectionW) * 180.f / M_PI);
247 
248  const float metric((openingAngleU + openingAngleV + openingAngleW) / 3.f);
249 
250  if (metric > m_maxAngularDeviation)
251  return false;
252 
253  return true;
254 }
255 
256 //------------------------------------------------------------------------------------------------------------------------------------------
257 
258 StatusCode ProtoShowerMatchingTool::ReadSettings(const TiXmlHandle xmlHandle)
259 {
260  PANDORA_RETURN_RESULT_IF_AND_IF(
261  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "SpineSlidingFitWindow", m_spineSlidingFitWindow));
262 
263  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxXSeparation", m_maxXSeparation));
264 
265  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxSeparation", m_maxSeparation));
266 
267  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "XExtrapolation", m_xExtrapolation));
268 
269  PANDORA_RETURN_RESULT_IF_AND_IF(
270  STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle, "MaxAngularDeviation", m_maxAngularDeviation));
271 
272  return STATUS_CODE_SUCCESS;
273 }
274 
275 } // 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.
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.
float m_xExtrapolation
Extrapolation distance in the x-direction.
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.