27 static std::atomic<bool> config_dumped{
false};
88 static std::atomic<bool> config_dumped{
false};
100 config_dumped =
true;
135 static std::atomic<bool> config_dumped{
false};
150 if (!config_dumped) {
152 config_dumped =
true;
160 static const unsigned int max_fifo_tbins = 1 << 5;
161 static const unsigned int max_fifo_pretrig = 1 << 5;
162 static const unsigned int max_drift_delay = 1 << 2;
163 static const unsigned int max_nplanes_hit_pretrig = 1 << 3;
164 static const unsigned int max_nplanes_hit_pattern = 1 << 3;
165 static const unsigned int max_nplanes_hit_accel_pretrig = 1 << 3;
166 static const unsigned int max_nplanes_hit_accel_pattern = 1 << 3;
167 static const unsigned int max_trig_mode = 1 << 2;
168 static const unsigned int max_accel_mode = 1 << 2;
180 max_nplanes_hit_accel_pretrig,
182 "nplanes_hit_accel_pretrig");
184 max_nplanes_hit_accel_pattern,
186 "nplanes_hit_accel_pattern");
211 static std::atomic<bool> config_dumped{
false};
214 config_dumped =
true;
227 <<
"+++ CSC geometry looks garbled; no emulation possible +++\n";
234 <<
" is not defined in current geometry! +++\n"
235 <<
"+++ CSC geometry looks garbled; no emulation possible +++\n";
244 <<
" numWireGroups = " <<
numWireGroups <<
"; ALCT emulation skipped! +++";
245 std::vector<CSCALCTDigi> emptyV;
260 const unsigned int min_layers =
265 unsigned int layersHit = 0;
268 if (!wire[i_layer][i_wire].
empty()) {
274 if (layersHit >= min_layers)
290 std::map<int, std::map<int, CSCALCTDigi::WireContainer>> hits_in_patterns;
291 hits_in_patterns.clear();
297 if (!chamber_empty) {
301 if (
unsigned(i_wire) >= max_wire)
304 unsigned int start_bx = 0;
306 while (start_bx < stop_bx) {
312 int ghost_cleared[2] = {0, 0};
322 int valid = (ghost_cleared[0] == 0) ? 1 : 0;
330 LogTrace(
"CSCAnodeLCTProcessor") <<
"Add one ALCT to list " <<
lct_list.back();
335 int valid = (ghost_cleared[1] == 0) ? 1 : 0;
344 LogTrace(
"CSCAnodeLCTProcessor") <<
"Add one ALCT to list " <<
lct_list.back();
376 digiV[i_layer].clear();
390 LogTrace(
"CSCAnodeLCTProcessor") <<
"found " <<
digiV[i_layer].size() <<
" wire digi(s) in layer " << i_layer
393 for (
const auto& wd :
digiV[i_layer]) {
394 LogTrace(
"CSCAnodeLCTProcessor") <<
" " << wd;
406 digiV[
id.layer() - 1].push_back(*digiIt);
415 for (
const auto& wd :
digiV[i_layer]) {
416 int i_wire = wd.getWireGroup() - 1;
417 std::vector<int> bx_times = wd.getTimeBinsOn();
423 <<
"+++ Found wire digi with wrong wire number = " << i_wire <<
" (max wires = " <<
numWireGroups
424 <<
"); skipping it... +++\n";
434 int last_time = -999;
436 wire[i_layer][i_wire].push_back(0);
437 wire[i_layer][i_wire].push_back(6);
439 for (
unsigned int i = 0;
i < bx_times.size();
i++) {
441 if (
i > 0 && bx_times[
i] == (bx_times[
i - 1] + 1))
446 <<
"Digi on layer " << i_layer <<
" wire " << i_wire <<
" at time " << bx_times[
i];
451 if (last_time < 0 || ((bx_times[
i] - last_time) >= 6)) {
452 wire[i_layer][i_wire].push_back(bx_times[
i]);
453 last_time = bx_times[
i];
457 LogTrace(
"CSCAnodeLCTProcessor") <<
"+++ Skipping wire digi: wire = " << i_wire <<
" layer = " << i_layer
458 <<
", bx = " << bx_times[
i] <<
" +++";
468 bool chamber_empty =
true;
469 int i_wire, i_layer, digi_num;
470 const unsigned int bits_in_pulse = 8 *
sizeof(
pulse[0][0]);
474 pulse[i_layer][i_wire] = 0;
478 for (
int j = 0;
j < 3;
j++)
485 if (!wire[i_layer][i_wire].
empty()) {
486 std::vector<int> bx_times = wire[i_layer][i_wire];
487 for (
unsigned int i = 0;
i < bx_times.size();
i++) {
489 if (bx_times[
i] < 0 || bx_times[
i] +
hit_persist >= bits_in_pulse) {
492 <<
"+++ BX time of wire digi (wire = " << i_wire <<
" layer = " << i_layer <<
") bx = " << bx_times[
i]
493 <<
" is not within the range (0-" << bits_in_pulse
494 <<
"] allowed for pulse extension. Skip this digi! +++\n";
500 chamber_empty =
false;
504 pulse[i_layer][i_wire] =
pulse[i_layer][i_wire] | (1 <<
bx);
508 LogTrace(
"CSCAnodeLCTProcessor") <<
"Wire digi: layer " << i_layer <<
" digi #" << ++digi_num
509 <<
" wire group " << i_wire <<
" time " << bx_times[
i];
511 std::ostringstream strstrm;
512 for (
int i = 1;
i <= 32;
i++) {
513 strstrm << ((
pulse[i_layer][i_wire] >> (32 -
i)) & 1);
515 LogTrace(
"CSCAnodeLCTProcessor") <<
" Pulse: " << strstrm.str();
523 if (
infoV > 1 && !chamber_empty) {
527 return chamber_empty;
531 int nPreTriggers = 0;
533 unsigned int layers_hit;
538 const unsigned int nplanes_hit_pretrig_acc =
548 for (
unsigned int bx_time = start_bx; bx_time < stop_bx; bx_time++) {
552 hit_layer[i_layer] =
false;
563 if (((
pulse[i_layer][this_wire] >> bx_time) & 1) == 1) {
565 if (!hit_layer[i_layer]) {
566 hit_layer[i_layer] =
true;
572 if (layers_hit >= pretrig_thresh[i_pattern]) {
575 LogTrace(
"CSCAnodeLCTProcessor") <<
"Pretrigger was satisfied for wire: " << key_wire
576 <<
" pattern: " << i_pattern <<
" bx_time: " << bx_time;
598 const int key_wire,
std::map<
int, std::map<int, CSCALCTDigi::WireContainer>>& hits_in_patterns) {
601 unsigned int temp_quality;
602 int this_wire, delta_wire;
605 const unsigned int nplanes_hit_pattern_acc =
609 const std::string ptn_label[] = {
"Accelerator",
"CollisionA",
"CollisionB"};
616 hit_layer[i_layer] =
false;
620 hits_single_pattern.clear();
622 for (
auto&
p : hits_single_pattern) {
626 double num_pattern_hits = 0., times_sum = 0.;
627 std::multiset<int> mset_for_median;
628 mset_for_median.clear();
635 this_wire = delta_wire + key_wire;
641 hits_single_pattern[i_layer][i_wire] = this_wire;
645 if (!hit_layer[i_layer]) {
648 hit_layer[i_layer] =
true;
651 <<
"bx_time: " <<
first_bx[key_wire] <<
" pattern: " << i_pattern <<
" keywire: " << key_wire
652 <<
" layer: " << i_layer <<
" quality: " << temp_quality;
656 if (
abs(delta_wire) < 2) {
660 for (
unsigned int dbx = 0; dbx <
hit_persist; dbx++) {
661 if (((
pulse[i_layer][this_wire] >> (first_bx_layer - 1)) & 1) == 1)
666 times_sum += (double)first_bx_layer;
667 num_pattern_hits += 1.;
668 mset_for_median.insert(first_bx_layer);
670 LogTrace(
"CSCAnodeLCTProcessor") <<
" 1st bx in layer: " << first_bx_layer <<
" sum bx: " << times_sum
671 <<
" #pat. hits: " << num_pattern_hits;
680 const int sz = mset_for_median.size();
682 std::multiset<int>::iterator im = mset_for_median.begin();
684 std::advance(im, sz / 2 - 1);
687 else if ((sz % 2) == 1)
692 #if defined(EDM_ML_DEBUG)
694 auto lt =
LogTrace(
"CSCAnodeLCTProcessor")
696 for (im = mset_for_median.begin(); im != mset_for_median.end(); im++) {
704 if (temp_quality >= pattern_thresh[i_pattern]) {
706 hits_in_patterns[key_wire][i_pattern] = hits_single_pattern;
712 if (i_pattern == 0) {
714 quality[key_wire][0] = temp_quality;
717 if (static_cast<int>(temp_quality) >
quality[key_wire][1]) {
718 quality[key_wire][1] = temp_quality;
719 quality[key_wire][2] = i_pattern - 1;
723 LogTrace(
"CSCAnodeLCTProcessor") <<
"Pattern found; keywire: " << key_wire <<
" type: " << ptn_label[i_pattern]
724 <<
" quality: " << temp_quality <<
"\n";
730 LogTrace(
"CSCAnodeLCTProcessor") <<
"Collision Pattern A is chosen"
732 else if (
quality[key_wire][2] == 1)
733 LogTrace(
"CSCAnodeLCTProcessor") <<
"Collision Pattern B is chosen"
745 for (
int key_wire = 0; key_wire <
numWireGroups; key_wire++) {
746 for (
int i_pattern = 0; i_pattern < 2; i_pattern++) {
747 ghost_cleared[key_wire][i_pattern] = 0;
750 int qual_this =
quality[key_wire][i_pattern];
753 int qual_prev = (key_wire > 0) ?
quality[key_wire - 1][i_pattern] : 0;
763 if (qual_prev >= qual_this)
764 ghost_cleared[key_wire][i_pattern] = 1;
767 ghost_cleared[key_wire][i_pattern] = 1;
773 if (ghost_cleared[key_wire][i_pattern] == 1) {
776 << ((i_pattern == 0) ?
"Accelerator" :
"Collision") <<
" pattern ghost cancelled on key_wire "
777 << key_wire <<
" q=" << qual_this <<
" by wire " << key_wire - 1 <<
" q=" << qual_prev;
786 if (qual_next > qual_this)
787 ghost_cleared[key_wire][i_pattern] = 1;
790 ghost_cleared[key_wire][i_pattern] = 1;
793 if (ghost_cleared[key_wire][i_pattern] == 1) {
796 << ((i_pattern == 0) ?
"Accelerator" :
"Collision") <<
" pattern ghost cancelled on key_wire "
797 << key_wire <<
" q=" << qual_this <<
" by wire " << key_wire + 1 <<
" q=" << qual_next;
807 for (
int key_wire = 0; key_wire <
numWireGroups; key_wire++) {
808 for (
int i_pattern = 0; i_pattern < 2; i_pattern++) {
809 if (ghost_cleared[key_wire][i_pattern] > 0) {
810 clear(key_wire, i_pattern);
819 for (
int i_pattern = 0; i_pattern < 2; i_pattern++) {
820 ghost_cleared[i_pattern] = 0;
825 int qual_this =
quality[key_wire][i_pattern];
834 if (not(
p.getKeyWG() == key_wire - 1 and 1 -
p.getAccelerator() == i_pattern))
837 bool ghost_cleared_prev =
false;
838 int qual_prev =
p.getQuality();
839 int first_bx_prev =
p.getBX();
842 <<
"ghost concellation logic " << ((i_pattern == 0) ?
"Accelerator" :
"Collision") <<
" key_wire "
843 << key_wire <<
" quality " << qual_this <<
" bx " <<
first_bx[key_wire] <<
" previous key_wire "
844 << key_wire - 1 <<
" quality " << qual_prev <<
" bx " <<
first_bx[key_wire - 1];
855 if (qual_prev >= qual_this)
856 ghost_cleared[i_pattern] = 1;
857 else if (qual_prev < qual_this)
858 ghost_cleared_prev =
true;
861 ghost_cleared[i_pattern] = 1;
864 ghost_cleared_prev =
true;
867 if (ghost_cleared[i_pattern] == 1) {
870 << ((i_pattern == 0) ?
"Accelerator" :
"Collision") <<
" pattern ghost cancelled on key_wire "
871 << key_wire <<
" q=" << qual_this <<
" by wire " << key_wire - 1 <<
" q=" << qual_prev;
875 if (ghost_cleared_prev) {
878 << ((i_pattern == 0) ?
"Accelerator" :
"Collision") <<
" pattern ghost cancelled on key_wire "
879 << key_wire - 1 <<
" q=" << qual_prev <<
" by wire " << key_wire <<
" q=" << qual_this;
894 int n_alct_all = 0, n_alct = 0;
899 for (
const auto&
p : fourBest) {
905 <<
"C:" <<
theChamber <<
" all " << n_alct_all <<
" found " << n_alct;
910 for (
const auto&
p : fourBest) {
911 const int bx =
p.getBX();
916 <<
"; skipping it... +++\n";
965 LogTrace(
"CSCAnodeLCTProcessor") << all_alcts.size() <<
" ALCTs at the input of best-track selector: ";
966 for (
const auto&
p : all_alcts) {
975 for (
const auto&
p : all_alcts) {
987 int accel =
p.getAccelerator();
988 int qual =
p.getQuality();
989 int wire =
p.getKeyWG();
996 if (!vA || qual > qA || (qual == qA && wire > wA)) {
999 if (!vB || qual > qB || (qual == qB && wire < wB)) {
1005 for (
int accel = 0; accel <= 1; accel++) {
1007 if (tA[
bx][accel].isValid()) {
1009 LogTrace(
"CSCAnodeLCTProcessor") <<
"tA: " << tA[
bx][accel];
1010 LogTrace(
"CSCAnodeLCTProcessor") <<
"tB: " << tB[
bx][accel];
1012 bestALCTs[
bx][accel] = tA[
bx][accel];
1015 if (tA[
bx][accel] != tB[
bx][accel] && tA[
bx][accel].getQuality() == tB[
bx][accel].getQuality()) {
1016 secondALCTs[
bx][accel] = tB[
bx][accel];
1022 for (
const auto&
p : all_alcts) {
1023 if (
p.isValid() &&
p.getAccelerator() == accel &&
p.getBX() ==
bx &&
1026 p.getKeyWG() >= secondALCTs[
bx][accel].
getKeyWG()) {
1027 secondALCTs[
bx][accel] =
p;
1036 std::vector<CSCALCTDigi> fourBest;
1039 if (bestALCTs[
bx][
i].isValid()) {
1040 fourBest.push_back(bestALCTs[
bx][
i]);
1044 if (secondALCTs[
bx][
i].isValid()) {
1045 fourBest.push_back(secondALCTs[
bx][
i]);
1051 LogTrace(
"CSCAnodeLCTProcessor") << fourBest.size() <<
" ALCTs selected: ";
1052 for (
const auto&
p : fourBest) {
1061 bool returnValue =
false;
1079 if (qual1 > qual2) {
1108 if (
quality[key_wire][1] > 0) {
1111 LogTrace(
"CSCAnodeLCTProcessor") <<
"trigMode(): collision track " << key_wire <<
" disabled"
1117 if (
quality[key_wire][0] > 0) {
1120 LogTrace(
"CSCAnodeLCTProcessor") <<
"trigMode(): accelerator track " << key_wire <<
" disabled"
1130 LogTrace(
"CSCAnodeLCTProcessor") <<
"trigMode(): collision track " << key_wire <<
" disabled"
1138 int promotionBit = 1 << 2;
1144 if (
quality[key_wire][0] > 0) {
1147 LogTrace(
"CSCAnodeLCTProcessor") <<
"alctMode(): accelerator track " << key_wire <<
" ignored"
1153 if (
quality[key_wire][1] > 0) {
1154 quality[key_wire][1] += promotionBit;
1156 LogTrace(
"CSCAnodeLCTProcessor") <<
"alctMode(): collision track " << key_wire <<
" promoted"
1162 if (
quality[key_wire][0] > 0) {
1163 quality[key_wire][0] += promotionBit;
1165 LogTrace(
"CSCAnodeLCTProcessor") <<
"alctMode(): accelerator track " << key_wire <<
" promoted"
1171 if (
quality[key_wire][1] > 0) {
1174 LogTrace(
"CSCAnodeLCTProcessor") <<
"alctMode(): collision track " << key_wire <<
" ignored"
1183 std::ostringstream strm;
1185 strm <<
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1186 strm <<
"+ ALCT configuration parameters: +\n";
1187 strm <<
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1188 strm <<
" fifo_tbins [total number of time bins in DAQ readout] = " <<
fifo_tbins <<
"\n";
1189 strm <<
" fifo_pretrig [start time of anode raw hits in DAQ readout] = " <<
fifo_pretrig <<
"\n";
1190 strm <<
" drift_delay [drift delay after pre-trigger, in 25 ns bins] = " <<
drift_delay <<
"\n";
1191 strm <<
" nplanes_hit_pretrig [min. number of layers hit for pre-trigger] = " <<
nplanes_hit_pretrig <<
"\n";
1192 strm <<
" nplanes_hit_pattern [min. number of layers hit for trigger] = " <<
nplanes_hit_pattern <<
"\n";
1193 strm <<
" nplanes_hit_accel_pretrig [min. number of layers hit for accel."
1195 strm <<
" nplanes_hit_accel_pattern [min. number of layers hit for accel."
1197 strm <<
" trig_mode [enabling/disabling collision/accelerator tracks] = " <<
trig_mode <<
"\n";
1198 strm <<
" accel_mode [preference to collision/accelerator tracks] = " <<
accel_mode <<
"\n";
1199 strm <<
" l1a_window_width [L1Accept window width, in 25 ns bins] = " <<
l1a_window_width <<
"\n";
1200 strm <<
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1201 LogDebug(
"CSCAnodeLCTProcessor") << strm.str();
1209 std::ostringstream strstrm;
1211 if (i_wire % 10 == 0) {
1213 strstrm << i_wire / 10;
1215 strstrm << (i_wire - 100) / 10;
1221 strstrm << i_wire % 10;
1226 if (!wire[i_layer][i_wire].
empty()) {
1227 std::vector<int> bx_times = wire[i_layer][i_wire];
1228 strstrm << std::hex << bx_times[0] <<
std::dec;
1234 LogTrace(
"CSCAnodeLCTProcessor") << strstrm.str();
1240 std::vector<CSCALCTDigi> tmpV;
1246 static std::atomic<int> late_tbins{
early_tbins + lct_bins};
1248 static std::atomic<int> ifois{0};
1252 <<
"+++ fifo_pretrig = " <<
fifo_pretrig <<
"; in-time ALCTs are not getting read-out!!! +++"
1259 <<
"+++ Allowed range of time bins, [0-" << late_tbins <<
"] exceeds max allowed, "
1261 <<
"+++ Set late_tbins to max allowed +++\n";
1269 const std::vector<CSCALCTDigi>& all_alcts =
getALCTs(nMaxALCTs);
1270 for (
const auto&
p : all_alcts) {
1278 LogDebug(
"CSCAnodeLCTProcessor") <<
" Do not report ALCT on keywire " <<
p.getKeyWG() <<
": found at bx " <<
bx
1279 <<
", whereas the earliest allowed bx is " <<
early_tbins + 1;
1284 if (
bx > late_tbins) {
1286 LogDebug(
"CSCAnodeLCTProcessor") <<
" Do not report ALCT on keywire " <<
p.getKeyWG() <<
": found at bx " <<
bx
1287 <<
", whereas the latest allowed bx is " << late_tbins;
1300 for (
auto&
p : tmpV) {
1306 for (
const auto& alct : tmpV) {
1315 std::vector<CSCALCTDigi> tmpV;
1335 std::ostringstream strstrm_header;
1336 LogTrace(
"CSCAnodeLCTProcessor") <<
"\n"
1337 <<
"Pattern: " << i_pattern <<
" Key wire: " << key_wire;
1338 for (
int i = 1;
i <= 32;
i++) {
1339 strstrm_header << ((32 -
i) % 10);
1341 LogTrace(
"CSCAnodeLCTProcessor") << strstrm_header.str();
1346 std::ostringstream strstrm_pulse;
1349 for (
int i = 1;
i <= 32;
i++) {
1350 strstrm_pulse << ((
pulse[i_layer][this_wire] >> (32 -
i)) & 1);
1352 LogTrace(
"CSCAnodeLCTProcessor") << strstrm_pulse.str() <<
" on layer " << i_layer <<
" wire " << this_wire;
1357 LogTrace(
"CSCAnodeLCTProcessor") <<
"-------------------------------------------";
1363 if (temp_quality > 3)
1364 Q = temp_quality - 3;
1372 for (
auto&
p : wireHits) {