1#include "TrigScint/TrigScintTrackProducer.h"
9 max_delta_ = ps.
get<
double>(
11 seeding_collection_ = ps.
get<std::string>(
12 "seeding_collection");
13 input_collections_ = ps.
get<std::vector<std::string>>(
14 "further_input_collections");
16 output_collection_ = ps.
get<std::string>(
"output_collection");
17 pass_name_ = ps.
get<std::string>(
"input_pass_name");
18 verbose_ = ps.
get<
int>(
"verbosity");
19 vert_bar_start_idx_ = ps.
get<
int>(
"vertical_bar_start_index");
20 n_bars_y_ = ps.
get<
int>(
"number_horizontal_bars");
21 bar_width_y_ = ps.
get<
double>(
"horizontal_bar_width");
22 bar_gap_y_ = ps.
get<
double>(
"horizontal_bar_gap");
23 n_bars_x_ = ps.
get<
int>(
"number_vertical_bars");
24 bar_width_x_ = ps.
get<
double>(
"vertical_bar_width");
25 bar_gap_x_ = ps.
get<
double>(
"vertical_bar_gap");
26 skip_last_ = ps.
get<
bool>(
"allow_skip_last_collection");
31 ldmx_log(info) <<
"In TrigScintTrackProducer: configure done!" << std::endl;
32 ldmx_log(info) <<
"Got parameters: \nSeeding: " << seeding_collection_
33 <<
"\nTolerance: " << max_delta_
34 <<
"\nInput: " << input_collections_.at(0) <<
" and "
35 << input_collections_.at(1)
36 <<
"\nInput pass name: " << pass_name_
37 <<
"\nAllow tracks with no hit in last collection: "
39 <<
"\nVertical bar start index: " << vert_bar_start_idx_
40 <<
"\nNumber of horizontal bars: " << n_bars_y_
41 <<
"\nHorizontal bar width: " << bar_width_y_
42 <<
"\nHorizontal bar gap: " << bar_gap_y_
43 <<
"\nNumber of vertical bars: " << n_bars_x_
44 <<
"\nVertical bar width: " << bar_width_x_
45 <<
"\nVertical bar gap: " << bar_gap_x_
46 <<
"\nOutput: " << output_collection_
47 <<
"\nVerbosity: " << verbose_;
50 y_conv_factor_ = (bar_width_y_ + bar_gap_y_) / 2.;
52 y_start_ = -(n_bars_y_ * (bar_width_y_ + bar_gap_y_) - bar_gap_y_) / 2.;
54 x_conv_factor_ = bar_width_x_ + bar_gap_x_;
56 x_start_ = -(n_bars_x_ * (bar_width_x_ + bar_gap_x_) - bar_gap_x_) / 2.;
71 <<
"TrigScintTrackProducer: produce() starts! Event number: "
72 <<
event.getEventHeader().getEventNumber();
74 if (!event.
exists(seeding_collection_, pass_name_)) {
75 ldmx_log(info) <<
"No collection called " << seeding_collection_
76 <<
"; skipping event";
81 if (!event.
exists(seeding_collection_, pass_name_)) {
82 ldmx_log(info) <<
"No collection called " << seeding_collection_
83 <<
"; skipping event";
87 seeding_collection_, pass_name_)};
88 uint num_seeds = seeds.size();
91 ldmx_log(debug) <<
"Got track seeding cluster collection "
92 << seeding_collection_ <<
" with " << num_seeds
96 if (!event.
exists(input_collections_.at(0), pass_name_)) {
97 ldmx_log(info) <<
"No collection called " << input_collections_.at(0)
98 <<
"; skipping event";
104 input_collections_.at(0), pass_name_)};
106 if (!event.
exists(input_collections_.at(1), pass_name_)) {
107 ldmx_log(info) <<
"No collection called "
108 << input_collections_.at(1)
110 <<
"; skipping event";
111 std::vector<ldmx::TrigScintTrack> empty{};
112 event.add(output_collection_, empty);
117 input_collections_.at(1), pass_name_)};
120 ldmx_log(debug) <<
"Got the other two pad collections:"
121 << input_collections_.at(0) <<
" with "
122 << clusters_pad1.size() <<
" entries, and "
123 << input_collections_.at(1) <<
" with "
124 << clusters_pad2.size() <<
" entries.";
127 std::vector<ldmx::TrigScintTrack> cleaned_tracks;
128 std::vector<ldmx::TrigScintTrack> cleaned_tracks_y;
129 std::vector<ldmx::TrigScintTrack> cleaned_tracks_x;
134 if (num_seeds && clusters_pad1.size()) {
139 for (
const auto &seed : seeds) {
142 float centroid = seed.getCentroid();
144 std::vector<ldmx::TrigScintTrack> track_candidates;
147 ldmx_log(debug) <<
"Got seed with centroid " << centroid;
153 for (
const auto &cluster1 : clusters_pad1) {
155 ldmx_log(debug) <<
"\tGot pad1 cluster with centroid "
156 << cluster1.getCentroid();
158 if (fabs(cluster1.getCentroid() - centroid) < max_delta_ ||
159 (centroid >= vert_bar_start_idx_
160 && seed.getCentroidX() == cluster1.getCentroidX())) {
164 if (centroid >= vert_bar_start_idx_ &&
165 seed.getCentroidY() < cluster1.getCentroidY()) {
168 ldmx_log(debug) <<
"\tSkipping impossible x cluster combination "
169 "with y flags (tag up) ("
170 << seed.getCentroidY() <<
" "
171 << cluster1.getCentroidY() <<
")";
179 ldmx_log(debug) <<
"\t\tIt is close enough!. Check pad2";
184 std::vector<ldmx::TrigScintCluster> cluster_vec = {seed, cluster1};
186 bool has_match_dn =
false;
188 for (
const auto &cluster2 : clusters_pad2) {
190 ldmx_log(debug) <<
"\tGot pad2 cluster with centroid "
191 << cluster2.getCentroid();
194 if (fabs(cluster2.getCentroid() - centroid) < max_delta_ ||
195 (centroid >= vert_bar_start_idx_
196 && seed.getCentroidX() == cluster2.getCentroidX())) {
200 if (centroid >= vert_bar_start_idx_ &&
201 (seed.getCentroidY() < cluster2.getCentroidY() ||
202 cluster1.getCentroidY() >
203 cluster2.getCentroidY())) {
206 <<
"\tSkipping impossible x cluster combination with y "
207 "flags (tag up dn) ("
208 << seed.getCentroidY() <<
" " << cluster1.getCentroidY()
209 <<
" " << cluster2.getCentroidY() <<
")";
217 ldmx_log(debug) <<
"\t\tIt is close enough!. Make a track";
222 std::vector<ldmx::TrigScintCluster> three_cluster_vec = {
223 seed, cluster1, cluster2};
232 track_candidates.push_back(track);
238 if (!has_match_dn && skip_last_) {
241 track_candidates.push_back(track);
254 if (track_candidates.size() == 0)
continue;
257 float min_residual = 1000;
260 if (track_candidates.size() > 1) {
264 ldmx_log(debug) <<
"Got " << track_candidates.size()
265 <<
" tracks to check.";
268 for (uint idx = 0; idx < track_candidates.size(); idx++) {
269 if ((track_candidates.at(idx)).getResidual() < min_residual) {
272 (track_candidates.at(idx)).getResidual();
276 <<
"Track at index " << idx
277 <<
" has smallest residual so far: " << min_residual;
287 tracks_.push_back(track_candidates.at(keep_idx));
289 ldmx_log(debug) <<
"Kept track at index " << keep_idx;
290 ldmx_log(trace) << track_candidates.at(keep_idx);
296 if (tracks_.size() == 0) {
298 ldmx_log(debug) <<
"No tracks found!";
300 std::vector<ldmx::TrigScintTrack> empty{};
301 event.add(output_collection_, empty);
312 std::vector keep_indices(tracks_.size(), 1);
314 ldmx_log(debug) <<
"vector of indices to keep has size "
315 << keep_indices.size();
317 for (uint idx = tracks_.size() - 1; idx > 0; idx--) {
321 for (
int idx_comp = idx - 1; idx_comp >= 0; idx_comp--) {
323 ldmx_log(debug) <<
"In track disambiguation loop, idx points at "
324 << idx <<
" and prev idx points at " << idx_comp;
332 std::vector<ldmx::TrigScintCluster> consts_1 =
334 std::vector<ldmx::TrigScintCluster> consts_2 =
338 <<
"In track disambiguation loop, got the two tracks, "
339 "with nConstituents "
340 << consts_1.size() <<
" and " << consts_2.size()
341 <<
", respectively. ";
344 if (consts_1[1].getCentroid() == consts_2[1].getCentroid() ||
345 (consts_1.size() > 2 && consts_2.size() > 2 &&
346 consts_1[2].getCentroid() ==
353 ldmx_log(debug) <<
"Found overlap! Tracks at index " << idx
354 <<
" and " << idx_comp;
355 ldmx_log(trace) << tracks_.at(idx);
356 ldmx_log(trace) << tracks_.at(idx_comp);
359 if ((tracks_.at(idx)).getResidual() <
360 (tracks_.at(idx_comp)).getResidual()) {
363 keep_indices.at(idx_comp) = 0;
367 keep_indices.at(idx) = 0;
385 for (uint idx = 0; idx < tracks_.size(); idx++) {
387 ldmx_log(debug) <<
"keep flag for idx " << idx <<
" is "
388 << keep_indices.at(idx);
390 if (keep_indices.at(idx)) {
392 cleaned_tracks.push_back(tracks_.at(idx));
395 ldmx_log(debug) <<
"After cleaning, keeping track at index " << idx
396 <<
": Centroid = " << (tracks_.at(idx)).getCentroid()
398 << (tracks_.at(idx)).getCentroidX()
400 << (tracks_.at(idx)).getCentroidY()
401 <<
"; track PE = " << (tracks_.at(idx)).getPE()
408 for (uint idx = 0; idx < tracks_.size(); idx++) {
409 ldmx_log(debug) <<
"Keeping track at index " << idx <<
":"
415 ldmx_log(debug) <<
"Running track x,y matching ";
418 if (cleaned_tracks.size() > 0) {
419 matchXYTracks(cleaned_tracks);
420 std::vector<ldmx::TrigScintTrack> matched_tracks =
426 for (
auto trk : matched_tracks) {
437 if (trk.getCentroid() >= vert_bar_start_idx_)
438 cleaned_tracks_x.push_back(trk);
440 cleaned_tracks_y.push_back(trk);
443 float centr = trk.getCentroid();
444 std::string coll_str = centr >= vert_bar_start_idx_ ?
"X" :
"Y";
445 coll_str = output_collection_ + coll_str;
446 ldmx_log(debug) <<
"saving track with centroid " << centr
447 <<
" to output track collection " << coll_str;
456 <<
"Not all pads had clusters; (maybe) skipping tracking attempt";
460 ldmx_log(debug) <<
"Done with tracking step. ";
463 event.add(output_collection_, cleaned_tracks);
466 event.add(output_collection_ +
"Y", cleaned_tracks_y);
467 event.add(output_collection_ +
"X", cleaned_tracks_x);
475 std::vector<ldmx::TrigScintCluster> clusters) {
482 float centroid_x = 0;
483 float centroid_y = 0;
484 float beam_efrac = 0;
486 for (uint i = 0; i < clusters.size(); i++) {
487 centroid += (clusters.at(i)).getCentroid();
488 centroid_x += (clusters.at(i)).getCentroidX();
489 centroid_y += (clusters.at(i)).getCentroidY();
491 beam_efrac += (clusters.at(i)).getBeamEfrac();
492 pe += (clusters.at(i)).getPE();
494 centroid /= clusters.size();
495 centroid_x /= clusters.size();
496 if (centroid >= vert_bar_start_idx_) {
499 <<
" -- In makeTrack made vertical bar track with centroid "
500 << centroid <<
" and y flag sum " << centroid_y;
512 centroid_y = (centroid_y + 1) * 2 * n_bars_y_ / 8.;
516 if (verbose_) ldmx_log(debug) <<
" -- new centroidY = " << centroid_y;
518 centroid_y /= clusters.size();
520 beam_efrac /= clusters.size();
521 pe /= clusters.size();
524 for (uint i = 0; i < clusters.size(); i++)
525 residual += ((clusters.at(i)).getCentroid() - centroid) *
526 ((clusters.at(i)).getCentroid() - centroid);
527 residual = sqrt(residual / clusters.size());
537 ldmx_log(debug) <<
" -- In makeTrack made track with centroid "
538 << centroid <<
" and residual " << residual <<
" and pe "
539 << pe <<
" from clusters with centroids";
540 for (uint i = 0; i < clusters.size(); i++)
541 ldmx_log(debug) <<
"\tpad " << i <<
": centroid "
542 << (clusters.at(i)).getCentroid();
549void TrigScintTrackProducer::matchXYTracks(
550 std::vector<ldmx::TrigScintTrack> &tracks) {
552 std::multimap<int, int>
554 std::multimap<int, int> x_idx_quad_map;
556 std::multimap<int, ldmx::TrigScintTrack> y_quad_map;
557 std::multimap<int, ldmx::TrigScintTrack> x_quad_map;
560 std::map<ldmx::TrigScintTrack, int> y_track_map;
561 std::map<ldmx::TrigScintTrack, int> x_track_map;
564 for (
auto trk : tracks) {
567 if (trk.getCentroidX() == -1) {
569 ldmx_log(debug) <<
" -- In matchXYTracks found y track at "
570 << trk.getCentroidY() <<
"; mapping to quad "
571 << (int)trk.getCentroidY() / 8 <<
" with trk index "
575 y_quad_map.insert(std::make_pair((
int)(trk.getCentroidY() / 8), trk));
576 y_track_map[trk] = trk_idx;
577 y_idx_quad_map.insert(
578 std::make_pair((
int)(trk.getCentroidY() / 8), trk_idx));
582 x_quad_map.insert(std::make_pair((
int)(trk.getCentroidY() / 8), trk));
583 x_track_map[trk] = trk_idx;
584 x_idx_quad_map.insert(
585 std::make_pair((
int)(trk.getCentroidY() / 8), trk_idx));
587 ldmx_log(debug) <<
" -- In matchXYTracks found x track at (x,y) = ("
588 << trk.getCentroidX() <<
", " << trk.getCentroidY()
589 <<
"); mapping to quad " << (int)trk.getCentroidY() / 8
590 <<
" with trk index " << trk_idx;
605 float sx0 = fabs(x_start_);
608 float sy0 = fabs(y_start_) / 4.;
612 for (
auto yitr = y_quad_map.begin(); yitr != y_quad_map.end(); ++yitr) {
613 int n_yin_quad = y_quad_map.count((*yitr).first);
614 int n_xin_quad = x_quad_map.count((*yitr).first);
615 float y{-9999.}, sy{-9999.}, x{-9999.}, x1{-9999.}, x2{-9999.}, sx1{-9999.},
616 sx2{-9999.}, y1{-9999.}, y2{-9999.}, sy1{-9999.}, sy2{-9999.};
618 float y0 = (*yitr).first * 8 + sy0;
625 if (n_xin_quad == 0) {
630 ldmx_log(debug) <<
"\t\t\t no x info in quad " << (*yitr).first
631 <<
"; will set x to middle of pad, pad half-width as "
632 "precision: set (x, sx)=("
633 << x <<
", " << sx <<
")";
635 else if (n_xin_quad ==
640 auto xitr = x_quad_map.find((*yitr).first);
641 x = ((*xitr).second).getCentroidX() * x_conv_factor_ + x_start_;
644 ldmx_log(debug) <<
"\t\t\t 1 x in quad " << (*yitr).first
645 <<
", getting (x, sx)=(" << x <<
", " << sx <<
")";
647 else if (n_xin_quad == 2) {
652 auto xitr1 = x_quad_map.lower_bound((*yitr).first);
653 auto xitr2 = x_quad_map.upper_bound((*yitr).first);
656 if (xitr1 != xitr2) {
657 x1 = ((*xitr1).second).getCentroidX() * x_conv_factor_ + x_start_;
658 x2 = ((*xitr2).second).getCentroidX() * x_conv_factor_ + x_start_;
659 sx1 = x_conv_factor_ / 2.;
662 sx = fabs(x1 - x2) / 2 *
665 ldmx_log(debug) <<
"\t\t -- 2 x in quad: setting y track x "
666 "coordinate to midpoint";
672 if (n_yin_quad == 1) {
674 y = ((*yitr).second).getCentroidY() * y_conv_factor_ + y_start_;
675 sy = ((*yitr).second).getResidual() * y_conv_factor_;
678 if (sy == 0) sy = 1. / 2 * y_conv_factor_;
680 if (n_xin_quad <= 1) {
684 auto xidx = x_idx_quad_map.find((*yitr).first);
685 auto yidx = y_idx_quad_map.find((*yitr).first);
686 tracks.at((*xidx).second).setPosition(x, y);
687 tracks.at((*xidx).second).setSigmaXY(sx, sy);
688 tracks.at((*yidx).second).setPosition(x, y);
689 tracks.at((*yidx).second).setSigmaXY(sx, sy);
691 ldmx_log(debug) <<
"\t\t\t in quad " << (*yitr).first
692 <<
", set (x, y) = (" << x <<
", " << y
693 <<
") and (sx, sy) = " << sx <<
", " << sy <<
")";
699 ldmx_log(debug) <<
"\t\t in quad " << (*yitr).first
700 <<
", not single x,y tracks: " << n_xin_quad
701 <<
" of x and " << n_yin_quad <<
" of y";
703 if (n_yin_quad == 2) {
706 auto yitr1 = y_quad_map.lower_bound((*yitr).first);
707 auto yitr2 = y_quad_map.upper_bound((*yitr).first);
709 y1 = ((*yitr1).second).getCentroidY() * y_conv_factor_ + y_start_;
710 y2 = ((*yitr2).second).getCentroidY() * y_conv_factor_ + y_start_;
711 sy1 = ((*yitr1).second).getResidual() * y_conv_factor_;
712 sy2 = ((*yitr2).second).getResidual() * y_conv_factor_;
714 sy = fabs(y1 - y2) / 2 * y_conv_factor_;
717 <<
"\t\t -- 2 y in quad: setting x track y coordinate to midpoint";
720 if (n_yin_quad == 1 &&
726 auto yidx = y_idx_quad_map.find((*yitr).first);
727 tracks.at((*yidx).second).setPosition(x, y);
728 tracks.at((*yidx).second).setSigmaXY(sx, sy);
730 int min_overlap_pe = 250;
731 if (((*yitr).second).getPE() < min_overlap_pe) {
738 ldmx_log(debug) <<
"\t\t -- Can't tell which x track should be "
739 "matched to single y track. Setting both x track "
740 "coordinates to y quadrant value:";
743 ldmx_log(debug) <<
"\t\t -- Found large PE count ("
744 << ((*yitr).second).getPE() <<
" > " << min_overlap_pe
745 <<
"), suggesting overlap! Setting both x track "
746 "coordinates to y track value:";
753 ldmx_log(debug) <<
"\t\t -- (x1, x2, y) = (" << x1 <<
", " << x2
754 <<
", " << y <<
") and (sx1, sx2, sy) = " << sx1 <<
", "
755 << sx2 <<
", " << sy <<
")";
758 auto xidx1 = x_idx_quad_map.lower_bound((*yitr).first);
759 auto xidx2 = x_idx_quad_map.upper_bound((*yitr).first);
761 tracks.at((*xidx1).second).setPosition(x1, y);
762 tracks.at((*xidx1).second).setSigmaXY(sx1, sy);
763 tracks.at((*xidx2).second).setPosition(x2, y);
764 tracks.at((*xidx2).second).setSigmaXY(sx2, sy);
767 else if (n_yin_quad == 2 && n_xin_quad == 1) {
772 auto xidx = x_idx_quad_map.find((*yitr).first);
773 tracks.at((*xidx).second).setPosition(x, y);
774 tracks.at((*xidx).second).setSigmaXY(sx, sy);
776 auto xitr = x_quad_map.lower_bound((*yitr).first);
777 int min_overlap_pe = 300;
778 if (((*xitr).second).getPE() < min_overlap_pe) {
781 <<
"\t\t just 1 x track with not-unusual PE in the quad -- can't "
782 "match; setting mid-point values for x ";
792 ldmx_log(debug) <<
"\t\t -- Found large PE count ("
793 << ((*xitr).second).getPE() <<
" > " << min_overlap_pe
794 <<
") in x track, suggesting overlap! Setting both y "
795 "track coordinates to x track value:";
798 ldmx_log(debug) <<
"\t\t -- (x, y1, y2) = (" << x <<
", " << y1 <<
", "
799 << y2 <<
") and (sx, sy1, sy2) = " << sx <<
", " << sy1
800 <<
", " << sy2 <<
")";
802 auto yidx1 = y_idx_quad_map.lower_bound((*yitr).first);
803 auto yidx2 = y_idx_quad_map.upper_bound((*yitr).first);
805 tracks.at((*yidx1).second).setPosition(x, y1);
806 tracks.at((*yidx1).second).setSigmaXY(sx, sy1);
807 tracks.at((*yidx2).second).setPosition(x, y2);
808 tracks.at((*yidx2).second).setSigmaXY(sx, sy2);
811 else if (n_yin_quad == 2 && n_xin_quad == 2) {
813 auto xidx1 = x_idx_quad_map.lower_bound((*yitr).first);
814 auto xidx2 = x_idx_quad_map.upper_bound((*yitr).first);
816 auto yidx1 = y_idx_quad_map.lower_bound((*yitr).first);
817 auto yidx2 = y_idx_quad_map.upper_bound((*yitr).first);
820 if (y_idx_quad_map.find((*yitr).first) == y_idx_quad_map.end())
821 ldmx_log(error) <<
"The two y tracks in the same quadrant at "
823 <<
" appear to not be found in the y track map! "
824 "investigate. Note that yidx1.first = "
826 <<
" and yidx2.first = " << (*yidx2).first;
828 tracks.at((*xidx1).second).setPosition(x1, y);
829 tracks.at((*xidx1).second).setSigmaXY(sx1, sy);
830 tracks.at((*xidx2).second).setPosition(x2, y);
831 tracks.at((*xidx2).second).setSigmaXY(sx2, sy);
833 tracks.at((*yidx1).second).setPosition(x, y1);
834 tracks.at((*yidx1).second).setSigmaXY(sx, sy1);
835 tracks.at((*yidx2).second).setPosition(x, y2);
836 tracks.at((*yidx2).second).setSigmaXY(sx, sy2);
839 ldmx_log(debug) <<
"\t\t -- in a 2 x 2 situaiton; midpoint y: " << y
840 <<
" for both x tracks, midpoint x: " << x
841 <<
" for both y tracks";
845 if (n_xin_quad > 2) {
847 ldmx_log(debug) <<
"\t\t -*-*-*- more than 2 x tracks in the same quad "
848 "-- nothing done about the x,y coordinates in this "
849 "situation -- implement if needed!!";
851 if (n_yin_quad > 2) {
853 ldmx_log(debug) <<
"\t\t -*-*-*- more than 2 y tracks in the same quad "
854 "-- nothing done about the x,y coordinates in this "
855 "situation -- implement if needed!!";
867 ldmx_log(debug) <<
"Process starts!";
873 ldmx_log(debug) <<
"Process ends!";
#define DECLARE_PRODUCER(CLASS)
Macro which allows the framework to construct a producer given its name during configuration.
Implements an event buffer system for storing event data.
bool exists(const std::string &name, const std::string &passName, bool unique=true) const
Check for the existence of an object or collection with the given name and pass name in the event.
Class encapsulating parameters for configuring a processor.
const T & get(const std::string &name) const
Retrieve the parameter of the given name.
Stores cluster information from the trigger scintillator pads.
Represents a track of trigger scintillator clusters.
void setCentroidX(float centroid)
Set the x centroid of the track.
void setResidual(float resid)
Set the detector ID residual of the track.
void setCentroidY(float centroid)
Set the y centroid of the track.
void setPE(float pe)
Set the average cluster pe of the track.
float getCentroid() const
Get the detector ID centroid of the track.
void addConstituent(TrigScintCluster cl)
Add a cluster to the list of track constituents.
void setCentroid(float centroid)
Set the detector ID centroid of the track.
void setBeamEfrac(float e)
Set beam energy fraction of hit.
std::vector< ldmx::TrigScintCluster > getConstituents() const
Get the cluster constituents of the track.
making tracks from trigger scintillator clusters
void configure(framework::config::Parameters &ps) override
Callback for the EventProcessor to configure itself from the given set of parameters.
void onProcessEnd() override
Callback for the EventProcessor to take any necessary action when the processing of events finishes,...
void produce(framework::Event &event) override
Process the event and put new data products into it.
void onProcessStart() override
Callback for the EventProcessor to take any necessary action when the processing of events starts,...