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