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_ && merged_densities[density->cluster_id_] &&
337 event_centroid_.
centroidY()) < centroid_radius) {
338
339
340
341 is_seed =
342 density->total_energy_ > rhoc_ && density->delta_ > delta_c_mod;
343 } else {
344 is_seed = density->total_energy_ > rhoc_ && density->delta_ > deltac_;
345 if (is_seed) {
346 ldmx_log(trace) << " Distance to event centroid: "
347 <<
dist(density->x_, density->y_,
350 }
351 }
352 bool is_outlier =
353 (density->total_energy_ < rhoc_) && (density->delta_ > deltao_);
354 density->cluster_id_ = -1;
355 if (is_seed) {
356 ldmx_log(trace) << " This is a Seed";
357 ldmx_log(trace) << " Distance to centroid: "
358 <<
dist(density->x_, density->y_,
361 << "; with delta " << density->delta_;
362 ldmx_log(trace) << " Setting cluster ID to " << k;
363 density->cluster_id_ = k;
364 k++;
365
366 cluster_stack.push(density->index_);
367 clusters.push_back(density->hits_);
368 cluster_energies.push_back(density->total_energy_);
369 layer_seeds.push_back(density);
370 } else if (!is_outlier) {
371 ldmx_log(trace) << " This is a Follower";
372 int& parent_index = density->follower_of_;
373 if (parent_index != -1)
374 followers[parent_index].push_back(density->index_);
375 else
376 ldmx_log(error)
377 << " Somehow found a follower with parent index -1: id = "
378 << density->index_;
379 } else {
380 ldmx_log(trace) << " This is an Outlier";
381 }
382 }
383
384 merged_densities.clear();
385 merged_densities.resize(densities.size());
386
387
388 while (cluster_stack.size() > 0) {
389 auto& d = densities[cluster_stack.top()];
390 cluster_stack.pop();
391 auto& cid = d->cluster_id_;
392
393 for (const auto follower_index : followers[d->index_]) {
394 auto& follower = densities[follower_index];
395
396 follower->cluster_id_ = cid;
397 cluster_energies[cid] += follower->total_energy_;
398
399 if (reclustering_ && cluster_energies[cid] > max_energy &&
400 delta_c_mod > 0.5 && clustering_loops_ < 100) {
401
402
403 merged_densities[cid] = true;
404 if (!energy_overload && clustering_loops_ == 99) {
405 ldmx_log(warn) << "Merging clusters, max cluster loops hit";
406 }
407 energy_overload = true;
408 if (clustering_loops_ != 1) {
409 goto endwhile;
410
411 }
412 }
413
414 clusters[cid].insert(std::end(clusters[cid]),
415 std::begin(follower->hits_),
416 std::end(follower->hits_));
417
418
419 cluster_stack.push(follower_index);
420 }
421 }
422
423
424 if (clustering_loops_ == 1 && energy_overload)
425 initial_cluster_nbr_ = clusters.size();
426 endwhile:;
427 } while (energy_overload);
428
429 if (!connecting_layers && nbr_of_layers_ > 1) {
430
431
432 for (auto& seed : layer_seeds) {
433 seed->delta_ = std::numeric_limits<float>::max();
434 seed->hits_ = clusters[seed->cluster_id_];
435 seed->total_energy_ = cluster_energies[seed->cluster_id_];
436 seed->index_ = seed_index_;
437 seed_index_++;
438 }
439
440 std::sort(layer_seeds.begin(), layer_seeds.end(),
441 [](const std::shared_ptr<Density>& a,
442 const std::shared_ptr<Density>& b) {
443 return a->total_energy_ > b->total_energy_;
444 });
445 }
446 return clusters;
447}
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).