9 #include "Pandora/AlgorithmHeaders.h" 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.1
f),
27 m_maxEventHits(
std::numeric_limits<unsigned
int>::
max()),
28 m_onlyAvailableCaloHits(true),
29 m_inputCaloHitListName(
"Input")
38 return STATUS_CODE_SUCCESS;
45 if (!this->GetPandora().GetSettings()->SingleHitTypeClusteringMode())
47 std::cout <<
"PreProcessingAlgorithm: expect Pandora to be configured in SingleHitTypeClusteringMode." <<
std::endl;
48 return STATUS_CODE_FAILURE;
55 catch (
const StatusCodeException &statusCodeException)
57 if (STATUS_CODE_OUT_OF_RANGE == statusCodeException.GetStatusCode())
59 std::cout <<
"PreProcessingAlgorithm: Excessive number of hits in event, skipping the reconstruction" <<
std::endl;
68 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
74 return STATUS_CODE_SUCCESS;
81 const CaloHitList *pCaloHitList(
nullptr);
82 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::GetList(*
this,
m_inputCaloHitListName, pCaloHitList));
84 if (pCaloHitList->empty())
88 throw StatusCodeException(STATUS_CODE_OUT_OF_RANGE);
90 CaloHitList selectedCaloHitListU, selectedCaloHitListV, selectedCaloHitListW;
92 for (
const CaloHit *
const pCaloHit : *pCaloHitList)
105 if (pCaloHit->GetInputEnergy() < std::numeric_limits<float>::epsilon())
107 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
108 std::cout <<
"PreProcessingAlgorithm: found a hit with zero energy, will remove it" <<
std::endl;
115 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
117 std::cout <<
"PreProcessingAlgorithm: found a hit with extent " << pCaloHit->GetCellLengthScale() <<
", require (" 124 if (TPC_VIEW_U == pCaloHit->GetHitType())
126 selectedCaloHitListU.push_back(pCaloHit);
128 else if (TPC_VIEW_V == pCaloHit->GetHitType())
130 selectedCaloHitListV.push_back(pCaloHit);
132 else if (TPC_VIEW_W == pCaloHit->GetHitType())
134 selectedCaloHitListW.push_back(pCaloHit);
138 CaloHitList filteredCaloHitListU, filteredCaloHitListV, filteredCaloHitListW;
143 CaloHitList filteredInputList;
144 filteredInputList.insert(filteredInputList.end(), filteredCaloHitListU.begin(), filteredCaloHitListU.end());
145 filteredInputList.insert(filteredInputList.end(), filteredCaloHitListV.begin(), filteredCaloHitListV.end());
146 filteredInputList.insert(filteredInputList.end(), filteredCaloHitListW.begin(), filteredCaloHitListW.end());
149 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList(*
this, filteredInputList,
m_filteredCaloHitListName));
152 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList(*
this, filteredCaloHitListU,
m_outputCaloHitListNameU));
155 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList(*
this, filteredCaloHitListV,
m_outputCaloHitListNameV));
158 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList(*
this, filteredCaloHitListW,
m_outputCaloHitListNameW));
165 CaloHitList emptyList;
170 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList(*
this, emptyList,
m_filteredCaloHitListName));
173 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList(*
this, emptyList,
m_outputCaloHitListNameU));
176 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList(*
this, emptyList,
m_outputCaloHitListNameV));
179 PANDORA_THROW_RESULT_IF(STATUS_CODE_SUCCESS, !=, PandoraContentApi::SaveList(*
this, emptyList,
m_outputCaloHitListNameW));
183 std::cout <<
"PreProcessingAlgorithm: Unable to create void calo hit lists" <<
std::endl;
195 kdTree.
build(hitKDNode2DList, hitsBoundingRegion2D);
198 for (
const CaloHit *
const pCaloHit1 : inputList)
204 kdTree.
search(searchRegionHits, found);
206 for (
const auto &
hit : found)
208 const CaloHit *
const pCaloHit2(
hit.data);
210 if (pCaloHit1 == pCaloHit2)
213 const float displacementSquared((pCaloHit2->GetPositionVector() - pCaloHit1->GetPositionVector()).GetMagnitudeSquared());
215 if (displacementSquared < std::numeric_limits<float>::epsilon())
217 const float deltaMip(pCaloHit2->GetMipEquivalentEnergy() > pCaloHit1->GetMipEquivalentEnergy());
219 if ((deltaMip > std::numeric_limits<float>::epsilon()) ||
220 ((std::fabs(deltaMip) < std::numeric_limits<float>::epsilon()) &&
221 (outputList.end() != std::find(outputList.begin(), outputList.end(), pCaloHit2))))
231 outputList.push_back(pCaloHit1);
235 if (PandoraContentApi::GetSettings(*this)->ShouldDisplayAlgorithmInfo())
236 std::cout <<
"PreProcessingAlgorithm: found two hits in same location, will remove lowest pulse height" <<
std::endl;
245 PANDORA_RETURN_RESULT_IF_AND_IF(
246 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MipEquivalentCut",
m_mipEquivalentCut));
248 PANDORA_RETURN_RESULT_IF_AND_IF(
249 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MinCellLengthScale",
m_minCellLengthScale));
251 PANDORA_RETURN_RESULT_IF_AND_IF(
252 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxCellLengthScale",
m_maxCellLengthScale));
254 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"SearchRegion1D",
m_searchRegion1D));
256 PANDORA_RETURN_RESULT_IF_AND_IF(STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"MaxEventHits",
m_maxEventHits));
258 PANDORA_RETURN_RESULT_IF_AND_IF(
259 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"OnlyAvailableCaloHits",
m_onlyAvailableCaloHits));
261 PANDORA_RETURN_RESULT_IF_AND_IF(
262 STATUS_CODE_SUCCESS, STATUS_CODE_NOT_FOUND, !=, XmlHelper::ReadValue(xmlHandle,
"InputCaloHitListName",
m_inputCaloHitListName));
264 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"OutputCaloHitListNameU",
m_outputCaloHitListNameU));
266 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"OutputCaloHitListNameV",
m_outputCaloHitListNameV));
268 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"OutputCaloHitListNameW",
m_outputCaloHitListNameW));
270 PANDORA_RETURN_RESULT_IF(STATUS_CODE_SUCCESS, !=, XmlHelper::ReadValue(xmlHandle,
"FilteredCaloHitListName",
m_filteredCaloHitListName));
274 return STATUS_CODE_SUCCESS;
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.
pandora::StatusCode Reset()
void GetFilteredCaloHitList(const pandora::CaloHitList &inputList, pandora::CaloHitList &outputList)
Clean up the input CaloHitList.
Box structure used to define 2D field. It'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.
unsigned int m_maxEventHits
The maximum number of hits in an event to proceed with the reconstruction.
std::string m_currentCaloHitListReplacement
The name of the calo hit list to replace the current list (optional)
std::string m_outputCaloHitListNameW
The output calo hit list name for TPC_VIEW_W hits.
Header file for the cluster helper class.
void build(std::vector< KDTreeNodeInfoT< DATA, DIM >> &eltList, const KDTreeBoxT< DIM > ®ion)
Build the KD tree from the "eltList" in the space define by "region".
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.
static int max(int a, int b)
Detector simulation of raw signals on wires.
std::string m_inputCaloHitListName
The input calo hit list name.
pandora::StatusCode Run()
void ProcessCaloHits()
Build separate CaloHitLists for each view.
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
void PopulateVoidCaloHitLists() noexcept
Build empty calo hit lists.
pandora::StatusCode ReadSettings(const pandora::TiXmlHandle xmlHandle)
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
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...
bool m_onlyAvailableCaloHits
Whether to only include available calo hits.
QTextStream & endl(QTextStream &s)