264 {
265 ldmx_log(trace) << "--- CLUSTERING ---";
266 ldmx_log(trace) << "Number of densities: " << densities.size()
267 << "; connecting_layers: " << connecting_layers
268 << "; layer_index: " << layer_index;
269 if (!connecting_layers && nbr_of_layers_ > 1) {
270
271 rhoc_ = layer_rho_c_[layer_index];
272 ldmx_log(trace) << "Setting rho_c on layer " << layer_index << " to "
273 << rhoc_;
274 if (layer_index * 2 - 1 < radius_.size()) {
275 deltac_ = radius_[layer_index * 2 - 1];
276 ldmx_log(trace) << "Setting delta_c on layer " << layer_index << " to "
277 << deltac_;
278 }
279 } else if (connecting_layers) {
280
281
282
283
284
285
286
287 }
288
289 bool energy_overload = false;
290 double max_energy = 10000.;
291 clustering_loops_ = 0;
292 double delta_c_mod = deltac_;
293 double centroid_radius = 10.;
294
295
296 std::vector<std::shared_ptr<Density>>& layer_seeds = seeds_[layer_index];
297
298
299 std::vector<std::vector<const ldmx::EcalHit*>> clusters;
300
301 std::vector<bool> merged_densities;
302 merged_densities.resize(densities.size());
303
304 std::vector<double> cluster_energies;
305 do {
306
307 if (energy_overload) {
308
309 delta_c_mod = delta_c_mod / 1.1;
310 ldmx_log(trace) << "Energy overload, new delta_cmod: " << delta_c_mod;
311 energy_overload = false;
312 }
313
314 clustering_loops_++;
315 ldmx_log(trace) << "Clustering loop " << clustering_loops_;
316
317
318 int k = 0;
319
320 layer_seeds.clear();
321 layer_seeds.reserve(densities.size());
322 clusters.clear();
323 clusters.reserve(densities.size());
324 cluster_energies.clear();
325 cluster_energies.reserve(densities.size());
326
327 std::stack<int> cluster_stack;
328
329 std::vector<std::vector<int>> followers;
330 followers.resize(densities.size());
331
332
333 for (auto& density : densities) {
334
335 ldmx_log(trace) << " Index: " << density->index_
336 << "; x: " << density->x_ << "; y: " << density->y_
337 << "; Energy: " << density->total_energy_
338 << " Parent ID: " << density->follower_of_
339 << "; Delta: " << density->delta_;
340
341 bool is_seed;
342 if (delta_c_mod != deltac_ && density->cluster_id_ >= 0 &&
343 merged_densities[density->cluster_id_] &&
345 event_centroid_.
centroidY()) < centroid_radius) {
346
347
348
349 is_seed =
350 density->total_energy_ > rhoc_ && density->delta_ > delta_c_mod;
351 } else {
352 is_seed = density->total_energy_ > rhoc_ && density->delta_ > deltac_;
353 if (is_seed) {
354 ldmx_log(trace) << " Distance to event centroid: "
355 <<
dist(density->x_, density->y_,
358 }
359 }
360 bool is_outlier =
361 (density->total_energy_ < rhoc_) && (density->delta_ > deltao_);
362 density->cluster_id_ = -1;
363 if (is_seed) {
364 ldmx_log(trace) << " This is a Seed";
365 ldmx_log(trace) << " Distance to centroid: "
366 <<
dist(density->x_, density->y_,
369 << "; with delta " << density->delta_;
370 ldmx_log(trace) << " Setting cluster ID to " << k;
371 density->cluster_id_ = k;
372 k++;
373
374 cluster_stack.push(density->index_);
375 clusters.push_back(density->hits_);
376 cluster_energies.push_back(density->total_energy_);
377 layer_seeds.push_back(density);
378 } else if (!is_outlier) {
379 ldmx_log(trace) << " This is a Follower";
380 int& parent_index = density->follower_of_;
381 if (parent_index != -1)
382 followers[parent_index].push_back(density->index_);
383 else
384 ldmx_log(error)
385 << " Somehow found a follower with parent index -1: id = "
386 << density->index_;
387 } else {
388 ldmx_log(trace) << " This is an Outlier";
389 }
390 }
391
392 merged_densities.clear();
393 merged_densities.resize(densities.size());
394
395
396 while (cluster_stack.size() > 0) {
397 auto& d = densities[cluster_stack.top()];
398 cluster_stack.pop();
399 auto& cid = d->cluster_id_;
400
401 for (const auto follower_index : followers[d->index_]) {
402 auto& follower = densities[follower_index];
403
404 follower->cluster_id_ = cid;
405 cluster_energies[cid] += follower->total_energy_;
406
407 if (reclustering_ && cluster_energies[cid] > max_energy &&
408 delta_c_mod > 0.5 && clustering_loops_ < 100) {
409
410
411 merged_densities[cid] = true;
412 if (!energy_overload && clustering_loops_ == 99) {
413 ldmx_log(warn) << "Merging clusters, max cluster loops hit";
414 }
415 energy_overload = true;
416 if (clustering_loops_ != 1) {
417 goto endwhile;
418
419 }
420 }
421
422 clusters[cid].insert(std::end(clusters[cid]),
423 std::begin(follower->hits_),
424 std::end(follower->hits_));
425
426
427 cluster_stack.push(follower_index);
428 }
429 }
430
431
432 if (clustering_loops_ == 1 && energy_overload)
433 initial_cluster_nbr_ = clusters.size();
434 endwhile:;
435 } while (energy_overload);
436
437 if (!connecting_layers && nbr_of_layers_ > 1) {
438
439
440 for (auto& seed : layer_seeds) {
441 seed->delta_ = std::numeric_limits<float>::max();
442 seed->hits_ = clusters[seed->cluster_id_];
443 seed->total_energy_ = cluster_energies[seed->cluster_id_];
444 seed->index_ = seed_index_;
445 seed_index_++;
446 }
447
448 std::sort(layer_seeds.begin(), layer_seeds.end(),
449 [](const std::shared_ptr<Density>& a,
450 const std::shared_ptr<Density>& b) {
451 return a->total_energy_ > b->total_energy_;
452 });
453 }
454 return clusters;
455}
T dist(T x1, T y1, T x2, T y2)
Euclidean distance between two points.
double centroidY() const
Get the centroid Y position (energy-weighted).
double centroidX() const
Get the centroid X position (energy-weighted).