File indexing completed on 2026-09-27 09:15:00
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef LC_KD_TREE_LINKER_TOOLS_TEMPLATED_H
0009 #define LC_KD_TREE_LINKER_TOOLS_TEMPLATED_H 1
0010
0011 #include "Api/PandoraContentApi.h"
0012
0013 #include "Objects/CaloHit.h"
0014 #include "Objects/CartesianVector.h"
0015 #include "Objects/Track.h"
0016
0017 #include "Pandora/PandoraInternal.h"
0018
0019 #include <array>
0020
0021 namespace pandora {
0022 class Algorithm;
0023 }
0024
0025
0026
0027 namespace lc_content {
0028
0029
0030
0031
0032
0033
0034 template <unsigned DIM>
0035 class KDTreeBoxT {
0036 public:
0037
0038
0039
0040 KDTreeBoxT();
0041
0042
0043
0044
0045
0046
0047 template <typename... Ts>
0048 KDTreeBoxT(Ts... dimargs);
0049
0050 std::array<float, DIM> dimmin;
0051 std::array<float, DIM> dimmax;
0052 };
0053
0054 typedef KDTreeBoxT<2> KDTreeBox;
0055 typedef KDTreeBoxT<3> KDTreeCube;
0056 typedef KDTreeBoxT<4> KDTreeTesseract;
0057
0058
0059
0060
0061
0062
0063
0064 template <typename DATA, unsigned DIM>
0065 class KDTreeNodeInfoT {
0066 public:
0067
0068
0069
0070 KDTreeNodeInfoT();
0071
0072
0073
0074
0075
0076
0077
0078 template <typename... Ts>
0079 KDTreeNodeInfoT(const DATA& d, Ts... dimargs);
0080
0081 DATA data;
0082 std::array<float, DIM> dims;
0083 };
0084
0085
0086
0087
0088
0089
0090 template <typename DATA, unsigned DIM>
0091 class KDTreeNodeT {
0092 public:
0093
0094
0095
0096 KDTreeNodeT();
0097
0098
0099
0100
0101
0102
0103
0104 void setAttributs(const KDTreeBoxT<DIM>& regionBox, const KDTreeNodeInfoT<DATA, DIM>& infoToStore);
0105
0106
0107
0108
0109
0110
0111 void setAttributs(const KDTreeBoxT<DIM>& regionBox);
0112
0113 KDTreeNodeInfoT<DATA, DIM> info;
0114 KDTreeNodeT<DATA, DIM>* left;
0115 KDTreeNodeT<DATA, DIM>* right;
0116 KDTreeBoxT<DIM> region;
0117 };
0118
0119
0120
0121
0122
0123
0124 template <typename T>
0125 class kdtree_type_adaptor {
0126 public:
0127
0128
0129
0130
0131
0132
0133
0134 static const pandora::CartesianVector& position(const T* const t);
0135 };
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147 std::pair<float, float> minmax(const float a, const float b);
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157 template <typename T>
0158 KDTreeCube fill_and_bound_3d_kd_tree(const MANAGED_CONTAINER<const T*>& points,
0159 std::vector<KDTreeNodeInfoT<const T*, 3>>& nodes);
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169 template <typename T>
0170 KDTreeCube fill_and_bound_3d_kd_tree_by_index(const std::vector<const T*>& points,
0171 std::vector<KDTreeNodeInfoT<unsigned, 3>>& nodes);
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183 template <typename T>
0184 KDTreeCube fill_and_bound_3d_kd_tree(const pandora::Algorithm* const caller, const MANAGED_CONTAINER<const T*>& points,
0185 std::vector<KDTreeNodeInfoT<const T*, 3>>& nodes, bool passthru = false);
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197 KDTreeTesseract fill_and_bound_4d_kd_tree(const pandora::Algorithm* const caller,
0198 const MANAGED_CONTAINER<const pandora::CaloHit*>& points,
0199 std::vector<KDTreeNodeInfoT<const pandora::CaloHit*, 4>>& nodes,
0200 bool passthru = false);
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212 KDTreeCube build_3d_kd_search_region(const pandora::CaloHit* const point, const float x_span, const float y_span,
0213 const float z_span);
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226 KDTreeTesseract build_4d_kd_search_region(const pandora::CaloHit* const point, const float x_span, const float y_span,
0227 const float z_span, const float search_layer);
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240 KDTreeTesseract build_4d_kd_search_region(const pandora::CartesianVector& pos, const float x_span, const float y_span,
0241 const float z_span, const float search_layer);
0242
0243
0244
0245
0246 template <unsigned DIM>
0247 inline KDTreeBoxT<DIM>::KDTreeBoxT() {}
0248
0249
0250
0251 template <unsigned DIM>
0252 template <typename... Ts>
0253 inline KDTreeBoxT<DIM>::KDTreeBoxT(Ts... dimargs) {
0254 static_assert(sizeof...(dimargs) == 2 * DIM, "Constructor requires 2*DIM args");
0255 std::vector<float> dims = {dimargs...};
0256
0257 for (unsigned i = 0; i < DIM; ++i) {
0258 dimmin[i] = dims[2 * i];
0259 dimmax[i] = dims[2 * i + 1];
0260 }
0261 }
0262
0263
0264
0265
0266 template <typename DATA, unsigned DIM>
0267 inline KDTreeNodeInfoT<DATA, DIM>::KDTreeNodeInfoT() : data() {}
0268
0269
0270
0271 template <typename DATA, unsigned DIM>
0272 template <typename... Ts>
0273 inline KDTreeNodeInfoT<DATA, DIM>::KDTreeNodeInfoT(const DATA& d, Ts... dimargs) : data(d), dims{{dimargs...}} {}
0274
0275
0276
0277
0278 template <typename DATA, unsigned DIM>
0279 inline KDTreeNodeT<DATA, DIM>::KDTreeNodeT() : left(nullptr), right(nullptr) {}
0280
0281
0282
0283 template <typename DATA, unsigned DIM>
0284 inline void KDTreeNodeT<DATA, DIM>::setAttributs(const KDTreeBoxT<DIM>& regionBox,
0285 const KDTreeNodeInfoT<DATA, DIM>& infoToStore) {
0286 info = infoToStore;
0287 region = regionBox;
0288 }
0289
0290
0291
0292 template <typename DATA, unsigned DIM>
0293 inline void KDTreeNodeT<DATA, DIM>::setAttributs(const KDTreeBoxT<DIM>& regionBox) {
0294 region = regionBox;
0295 }
0296
0297
0298
0299 template <>
0300 inline const pandora::CartesianVector&
0301 kdtree_type_adaptor<const pandora::Track>::position(const pandora::Track* const t) {
0302 return t->GetTrackStateAtCalorimeter().GetPosition();
0303 }
0304
0305 template <>
0306 inline const pandora::CartesianVector&
0307 kdtree_type_adaptor<const pandora::CaloHit>::position(const pandora::CaloHit* const t) {
0308 return t->GetPositionVector();
0309 }
0310
0311 template <>
0312 inline const pandora::CartesianVector&
0313 kdtree_type_adaptor<const pandora::CartesianVector>::position(const pandora::CartesianVector* const t) {
0314 return *t;
0315 }
0316
0317
0318
0319 template <typename T>
0320 KDTreeCube fill_and_bound_3d_kd_tree(const MANAGED_CONTAINER<const T*>& points,
0321 std::vector<KDTreeNodeInfoT<const T*, 3>>& nodes) {
0322 std::array<float, 3> minpos{{0.f, 0.f, 0.f}}, maxpos{{0.f, 0.f, 0.f}};
0323
0324 unsigned i = 0;
0325
0326 for (const T* const point : points) {
0327 const pandora::CartesianVector& pos = kdtree_type_adaptor<const T>::position(point);
0328 nodes.emplace_back(point, pos.GetX(), pos.GetY(), pos.GetZ());
0329
0330 if (0 == i) {
0331 minpos[0] = pos.GetX();
0332 minpos[1] = pos.GetY();
0333 minpos[2] = pos.GetZ();
0334 maxpos[0] = pos.GetX();
0335 maxpos[1] = pos.GetY();
0336 maxpos[2] = pos.GetZ();
0337 } else {
0338 minpos[0] = std::min(pos.GetX(), minpos[0]);
0339 minpos[1] = std::min(pos.GetY(), minpos[1]);
0340 minpos[2] = std::min(pos.GetZ(), minpos[2]);
0341 maxpos[0] = std::max(pos.GetX(), maxpos[0]);
0342 maxpos[1] = std::max(pos.GetY(), maxpos[1]);
0343 maxpos[2] = std::max(pos.GetZ(), maxpos[2]);
0344 }
0345
0346 ++i;
0347 }
0348
0349 return KDTreeCube(minpos[0], maxpos[0], minpos[1], maxpos[1], minpos[2], maxpos[2]);
0350 }
0351
0352
0353
0354 template <typename T>
0355 KDTreeCube fill_and_bound_3d_kd_tree_by_index(const std::vector<const T*>& points,
0356 std::vector<KDTreeNodeInfoT<unsigned, 3>>& nodes) {
0357 std::array<float, 3> minpos{{0.f, 0.f, 0.f}}, maxpos{{0.f, 0.f, 0.f}};
0358
0359 unsigned i = 0;
0360
0361 for (const T* const point : points) {
0362 const pandora::CartesianVector& pos = kdtree_type_adaptor<const T>::position(point);
0363 nodes.emplace_back(i, pos.GetX(), pos.GetY(), pos.GetZ());
0364
0365 if (0 == i) {
0366 minpos[0] = pos.GetX();
0367 minpos[1] = pos.GetY();
0368 minpos[2] = pos.GetZ();
0369 maxpos[0] = pos.GetX();
0370 maxpos[1] = pos.GetY();
0371 maxpos[2] = pos.GetZ();
0372 } else {
0373 minpos[0] = std::min(pos.GetX(), minpos[0]);
0374 minpos[1] = std::min(pos.GetY(), minpos[1]);
0375 minpos[2] = std::min(pos.GetZ(), minpos[2]);
0376 maxpos[0] = std::max(pos.GetX(), maxpos[0]);
0377 maxpos[1] = std::max(pos.GetY(), maxpos[1]);
0378 maxpos[2] = std::max(pos.GetZ(), maxpos[2]);
0379 }
0380
0381 ++i;
0382 }
0383
0384 return KDTreeCube(minpos[0], maxpos[0], minpos[1], maxpos[1], minpos[2], maxpos[2]);
0385 }
0386
0387
0388
0389 template <typename T>
0390 KDTreeCube fill_and_bound_3d_kd_tree(const pandora::Algorithm* const caller, const MANAGED_CONTAINER<const T*>& points,
0391 std::vector<KDTreeNodeInfoT<const T*, 3>>& nodes, bool passthru) {
0392 std::array<float, 3> minpos{{0.f, 0.f, 0.f}}, maxpos{{0.f, 0.f, 0.f}};
0393
0394 unsigned i = 0;
0395
0396 for (const T* const point : points) {
0397 if (!passthru && !PandoraContentApi::IsAvailable(*caller, point))
0398 continue;
0399
0400 const pandora::CartesianVector& pos = kdtree_type_adaptor<const T>::position(point);
0401 nodes.emplace_back(point, pos.GetX(), pos.GetY(), pos.GetZ());
0402
0403 if (0 == i) {
0404 minpos[0] = pos.GetX();
0405 minpos[1] = pos.GetY();
0406 minpos[2] = pos.GetZ();
0407 maxpos[0] = pos.GetX();
0408 maxpos[1] = pos.GetY();
0409 maxpos[2] = pos.GetZ();
0410 } else {
0411 minpos[0] = std::min(pos.GetX(), minpos[0]);
0412 minpos[1] = std::min(pos.GetY(), minpos[1]);
0413 minpos[2] = std::min(pos.GetZ(), minpos[2]);
0414 maxpos[0] = std::max(pos.GetX(), maxpos[0]);
0415 maxpos[1] = std::max(pos.GetY(), maxpos[1]);
0416 maxpos[2] = std::max(pos.GetZ(), maxpos[2]);
0417 }
0418
0419 ++i;
0420 }
0421
0422 return KDTreeCube(minpos[0], maxpos[0], minpos[1], maxpos[1], minpos[2], maxpos[2]);
0423 }
0424
0425 }
0426
0427 #endif