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