LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
PreProcessingAlgorithm.cc
Go to the documentation of this file.
1 
9 #include "Pandora/AlgorithmHeaders.h"
10 
12 
14 
16 
17 using namespace pandora;
18 
19 namespace lar_content
20 {
21 
22 PreProcessingAlgorithm::PreProcessingAlgorithm() :
23  m_mipEquivalentCut(std::numeric_limits<float>::epsilon()),
24  m_minCellLengthScale(std::numeric_limits<float>::epsilon()),
25  m_maxCellLengthScale(3.f),
26  m_searchRegion1D(0.1f),
27  m_onlyAvailableCaloHits(true),
28  m_inputCaloHitListName("Input")
29 {
30 }
31 
32 //------------------------------------------------------------------------------------------------------------------------------------------
33 
35 {
36  m_processedHits.clear();
37  return STATUS_CODE_SUCCESS;
38 }
39 
40 //------------------------------------------------------------------------------------------------------------------------------------------
41 
43 {
44  if (!this->GetPandora().GetSettings()->SingleHitTypeClusteringMode())
45  {
46  std::cout << "PreProcessingAlgorithm: expect Pandora to be configured in SingleHitTypeClusteringMode." << std::endl;
47  return STATUS_CODE_FAILURE;
48  }
49 
50  try
51  {
52  this->ProcessCaloHits();
53  }
54  catch (StatusCodeException &)
55  {
56  }
57 
59  {
60  if (STATUS_CODE_SUCCESS != PandoraContentApi::ReplaceCurrentList<CaloHit>(*this, m_currentCaloHitListReplacement))
61  {
62  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
63  std::cout << "PreProcessingAlgorithm: could not replace current calo hit list with list named: " << m_currentCaloHitListReplacement << std::endl;
64  }
65  }
66 
67  return STATUS_CODE_SUCCESS;
68 }
69 
70 //------------------------------------------------------------------------------------------------------------------------------------------
71 
73 {
74  const CaloHitList *pCaloHitList(nullptr);
75  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*this, m_inputCaloHitListName, pCaloHitList));
76 
77  if (pCaloHitList->empty())
78  return;
79 
80  CaloHitList selectedCaloHitListU, selectedCaloHitListV, selectedCaloHitListW;
81 
82  for (const CaloHit *const pCaloHit : *pCaloHitList)
83  {
84  if (m_processedHits.count(pCaloHit))
85  continue;
86 
87  (void) m_processedHits.insert(pCaloHit);
88 
89  if (m_onlyAvailableCaloHits && !PandoraContentApi::IsAvailable(*this, pCaloHit))
90  continue;
91 
92  if (pCaloHit->GetMipEquivalentEnergy() < m_mipEquivalentCut)
93  continue;
94 
95  if (pCaloHit->GetInputEnergy() < std::numeric_limits<float>::epsilon())
96  {
97  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
98  std::cout << "PreProcessingAlgorithm: found a hit with zero energy, will remove it" << std::endl;
99 
100  continue;
101  }
102 
103  if ((pCaloHit->GetCellLengthScale() < m_minCellLengthScale) || (pCaloHit->GetCellLengthScale() > m_maxCellLengthScale))
104  {
105  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
106  {
107  std::cout << "PreProcessingAlgorithm: found a hit with extent " << pCaloHit->GetCellLengthScale()
108  << ", require (" << m_minCellLengthScale << " - " << m_maxCellLengthScale << "), will remove it" << std::endl;
109  }
110 
111  continue;
112  }
113 
114  if (TPC_VIEW_U == pCaloHit->GetHitType())
115  {
116  selectedCaloHitListU.push_back(pCaloHit);
117  }
118  else if (TPC_VIEW_V == pCaloHit->GetHitType())
119  {
120  selectedCaloHitListV.push_back(pCaloHit);
121  }
122  else if (TPC_VIEW_W == pCaloHit->GetHitType())
123  {
124  selectedCaloHitListW.push_back(pCaloHit);
125  }
126  }
127 
128  CaloHitList filteredCaloHitListU, filteredCaloHitListV, filteredCaloHitListW;
129  this->GetFilteredCaloHitList(selectedCaloHitListU, filteredCaloHitListU);
130  this->GetFilteredCaloHitList(selectedCaloHitListV, filteredCaloHitListV);
131  this->GetFilteredCaloHitList(selectedCaloHitListW, filteredCaloHitListW);
132 
133  CaloHitList filteredInputList;
134  filteredInputList.insert(filteredInputList.end(), filteredCaloHitListU.begin(), filteredCaloHitListU.end());
135  filteredInputList.insert(filteredInputList.end(), filteredCaloHitListV.begin(), filteredCaloHitListV.end());
136  filteredInputList.insert(filteredInputList.end(), filteredCaloHitListW.begin(), filteredCaloHitListW.end());
137 
138  if (!filteredInputList.empty() && !m_filteredCaloHitListName.empty())
139  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList(*this, filteredInputList, m_filteredCaloHitListName));
140 
141  if (!filteredCaloHitListU.empty() && !m_outputCaloHitListNameU.empty())
142  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList(*this, filteredCaloHitListU, m_outputCaloHitListNameU));
143 
144  if (!filteredCaloHitListV.empty() && !m_outputCaloHitListNameV.empty())
145  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList(*this, filteredCaloHitListV, m_outputCaloHitListNameV));
146 
147  if (!filteredCaloHitListW.empty() && !m_outputCaloHitListNameW.empty())
148  PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList(*this, filteredCaloHitListW, m_outputCaloHitListNameW));
149 }
150 
151 //------------------------------------------------------------------------------------------------------------------------------------------
152 
153 void PreProcessingAlgorithm::GetFilteredCaloHitList(const CaloHitList &inputList, CaloHitList &outputList)
154 {
155  HitKDTree2D kdTree;
156  HitKDNode2DList hitKDNode2DList;
157 
158  KDTreeBox hitsBoundingRegion2D = fill_and_bound_2d_kd_tree(inputList, hitKDNode2DList);
159  kdTree.build(hitKDNode2DList, hitsBoundingRegion2D);
160 
161  // Remove hits that are in the same physical location!
162  for (const CaloHit *const pCaloHit1 : inputList)
163  {
164  bool isUnique(true);
166 
167  HitKDNode2DList found;
168  kdTree.search(searchRegionHits, found);
169 
170  for (const auto &hit : found)
171  {
172  const CaloHit *const pCaloHit2(hit.data);
173 
174  if (pCaloHit1 == pCaloHit2)
175  continue;
176 
177  const float displacementSquared((pCaloHit2->GetPositionVector() - pCaloHit1->GetPositionVector()).GetMagnitudeSquared());
178 
179  if (displacementSquared < std::numeric_limits<float>::epsilon())
180  {
181  const float deltaMip(pCaloHit2->GetMipEquivalentEnergy() > pCaloHit1->GetMipEquivalentEnergy());
182 
183  if ((deltaMip > std::numeric_limits<float>::epsilon()) ||
184  ((std::fabs(deltaMip) < std::numeric_limits<float>::epsilon()) && (outputList.end() != std::find(outputList.begin(), outputList.end(), pCaloHit2))))
185  {
186  isUnique = false;
187  break;
188  }
189  }
190  }
191 
192  if (isUnique)
193  {
194  outputList.push_back(pCaloHit1);
195  }
196  else
197  {
198  if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
199  std::cout << "PreProcessingAlgorithm: found two hits in same location, will remove lowest pulse height" << std::endl;
200  }
201  }
202 }
203 
204 //------------------------------------------------------------------------------------------------------------------------------------------
205 
206 StatusCode PreProcessingAlgorithm::ReadSettings(const TiXmlHandle xmlHandle)
207 {
208  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
209  "MipEquivalentCut", m_mipEquivalentCut));
210 
211  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
212  "MinCellLengthScale", m_minCellLengthScale));
213 
214  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
215  "MaxCellLengthScale", m_maxCellLengthScale));
216 
217  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
218  "SearchRegion1D", m_searchRegion1D));
219 
220  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
221  "OnlyAvailableCaloHits", m_onlyAvailableCaloHits));
222 
223  PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
224  "InputCaloHitListName", m_inputCaloHitListName));
225 
226  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
227  "OutputCaloHitListNameU", m_outputCaloHitListNameU));
228 
229  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
230  "OutputCaloHitListNameV", m_outputCaloHitListNameV));
231 
232  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
233  "OutputCaloHitListNameW", m_outputCaloHitListNameW));
234 
235  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
236  "FilteredCaloHitListName", m_filteredCaloHitListName));
237 
238  PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
239  "CurrentCaloHitListReplacement", m_currentCaloHitListReplacement));
240 
241  return STATUS_CODE_SUCCESS;
242 }
243 
244 } // namespace lar_content
std::string m_outputCaloHitListNameV
The output calo hit list name for TPC_VIEW_V hits.
Header file for the kd tree linker algo template class.
void GetFilteredCaloHitList(const pandora::CaloHitList &inputList, pandora::CaloHitList &outputList)
Clean up the input CaloHitList.
Class that implements the KDTree partition of 2D space and a closest point search algorithm...
Box structure used to define 2D field. It&#39;s used in KDTree building step to divide the detector space...
float m_maxCellLengthScale
The maximum length scale for calo hit.
float m_mipEquivalentCut
Minimum mip equivalent energy for calo hit.
STL namespace.
std::string m_currentCaloHitListReplacement
The name of the calo hit list to replace the current list (optional)
TFile f
Definition: plotHisto.C:6
void search(const KDTreeBoxT< DIM > &searchBox, std::vector< KDTreeNodeInfoT< DATA, DIM > > &resRecHitList)
Search in the KDTree for all points that would be contained in the given searchbox The founded points...
std::string m_outputCaloHitListNameW
The output calo hit list name for TPC_VIEW_W hits.
Header file for the cluster helper class.
std::vector< HitKDNode2D > HitKDNode2DList
std::string m_filteredCaloHitListName
The output calo hit list name for all U, V and W hits.
float m_minCellLengthScale
The minimum length scale for calo hit.
std::string m_outputCaloHitListNameU
The output calo hit list name for TPC_VIEW_U hits.
Detector simulation of raw signals on wires.
std::string m_inputCaloHitListName
The input calo hit list name.
void ProcessCaloHits()
Build separate CaloHitLists for each view.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
KDTreeBox fill_and_bound_2d_kd_tree(const MANAGED_CONTAINER< const T * > &points, std::vector< KDTreeNodeInfoT< const T *, 2 > > &nodes)
fill_and_bound_2d_kd_tree
float m_searchRegion1D
Search region, applied to each dimension, for look-up from kd-trees.
Header file for the pre processing algorithm class.
pandora::CaloHitSet m_processedHits
The set of all previously processed calo hits.
KDTreeBox build_2d_kd_search_region(const pandora::CaloHit *const point, const float x_span, const float z_span)
build_2d_kd_search_region
bool m_onlyAvailableCaloHits
Whether to only include available calo hits.
void build(std::vector< KDTreeNodeInfoT< DATA, DIM > > &eltList, const KDTreeBoxT< DIM > &region)
Build the KD tree from the "eltList" in the space define by "region".