27 static std::atomic<bool> config_dumped{
false};
86 static std::atomic<bool> config_dumped{
false};
136 static std::atomic<bool> config_dumped{
false};
151 if (!config_dumped) {
154 config_dumped =
true;
162 static const unsigned int max_fifo_tbins = 1 << 5;
163 static const unsigned int max_fifo_pretrig = 1 << 5;
164 static const unsigned int max_drift_delay = 1 << 2;
165 static const unsigned int max_nplanes_hit_pretrig = 1 << 3;
166 static const unsigned int max_nplanes_hit_pattern = 1 << 3;
167 static const unsigned int max_nplanes_hit_accel_pretrig = 1 << 3;
168 static const unsigned int max_nplanes_hit_accel_pattern = 1 << 3;
169 static const unsigned int max_trig_mode = 1 << 2;
170 static const unsigned int max_accel_mode = 1 << 2;
182 max_nplanes_hit_accel_pretrig,
184 "nplanes_hit_accel_pretrig");
186 max_nplanes_hit_accel_pattern,
188 "nplanes_hit_accel_pattern");
216 static std::atomic<bool> config_dumped{
false};
220 config_dumped =
true;
234 <<
"+++ CSC geometry looks garbled; no emulation possible +++\n";
242 <<
" is not defined in current geometry! +++\n"
243 <<
"+++ CSC geometry looks garbled; no emulation possible +++\n";
253 <<
" numWireGroups = " <<
numWireGroups <<
"; ALCT emulation skipped! +++";
254 std::vector<CSCALCTDigi> emptyV;
269 const unsigned int min_layers =
274 unsigned int layersHit = 0;
277 if (!wire[i_layer][i_wire].
empty()) {
283 if (layersHit >= min_layers)
304 if (!chamber_empty) {
306 unsigned int start_bx = 0;
308 while (start_bx < stop_bx) {
314 int ghost_cleared[2] = {0, 0};
324 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;
341 LogTrace(
"CSCAnodeLCTProcessor") <<
"Add one ALCT to list " <<
lct_list.back();
373 digiV[i_layer].clear();
387 LogTrace(
"CSCAnodeLCTProcessor") <<
"found " <<
digiV[i_layer].size() <<
" wire digi(s) in layer " << i_layer
390 for (
const auto& wd :
digiV[i_layer]) {
391 LogTrace(
"CSCAnodeLCTProcessor") <<
" " << wd;
403 digiV[
id.layer() - 1].push_back(*digiIt);
412 for (
const auto& wd :
digiV[i_layer]) {
413 int i_wire = wd.getWireGroup() - 1;
414 std::vector<int> bx_times = wd.getTimeBinsOn();
420 <<
"+++ Found wire digi with wrong wire number = " << i_wire <<
" (max wires = " <<
numWireGroups
421 <<
"); skipping it... +++\n";
431 int last_time = -999;
433 wire[i_layer][i_wire].push_back(0);
434 wire[i_layer][i_wire].push_back(6);
436 for (
unsigned int i = 0;
i < bx_times.size();
i++) {
438 if (
i > 0 && bx_times[
i] == (bx_times[
i - 1] + 1))
443 <<
"Digi on layer " << i_layer <<
" wire " << i_wire <<
" at time " << bx_times[
i];
448 if (last_time < 0 || ((bx_times[
i] - last_time) >= 6)) {
449 wire[i_layer][i_wire].push_back(bx_times[
i]);
450 last_time = bx_times[
i];
454 LogTrace(
"CSCAnodeLCTProcessor") <<
"+++ Skipping wire digi: wire = " << i_wire <<
" layer = " << i_layer
455 <<
", bx = " << bx_times[
i] <<
" +++";
465 bool chamber_empty =
true;
466 int i_wire, i_layer, digi_num;
467 const unsigned int bits_in_pulse = 8 *
sizeof(
pulse[0][0]);
471 pulse[i_layer][i_wire] = 0;
475 for (
int j = 0;
j < 3;
j++)
482 if (!wire[i_layer][i_wire].
empty()) {
483 std::vector<int> bx_times = wire[i_layer][i_wire];
484 for (
unsigned int i = 0;
i < bx_times.size();
i++) {
486 if (bx_times[
i] < 0 || bx_times[
i] +
hit_persist >= bits_in_pulse) {
489 <<
"+++ BX time of wire digi (wire = " << i_wire <<
" layer = " << i_layer <<
") bx = " << bx_times[
i]
490 <<
" is not within the range (0-" << bits_in_pulse
491 <<
"] allowed for pulse extension. Skip this digi! +++\n";
497 chamber_empty =
false;
501 pulse[i_layer][i_wire] =
pulse[i_layer][i_wire] | (1 <<
bx);
505 LogTrace(
"CSCAnodeLCTProcessor") <<
"Wire digi: layer " << i_layer <<
" digi #" << ++digi_num
506 <<
" wire group " << i_wire <<
" time " << bx_times[
i];
508 std::ostringstream strstrm;
509 for (
int i = 1;
i <= 32;
i++) {
510 strstrm << ((
pulse[i_layer][i_wire] >> (32 -
i)) & 1);
512 LogTrace(
"CSCAnodeLCTProcessor") <<
" Pulse: " << strstrm.str();
520 if (
infoV > 1 && !chamber_empty) {
524 return chamber_empty;
528 int nPreTriggers = 0;
530 unsigned int layers_hit;
532 int this_layer, this_wire;
535 const unsigned int nplanes_hit_pretrig_acc =
545 for (
unsigned int bx_time = start_bx; bx_time < stop_bx; bx_time++) {
548 hit_layer[i_layer] =
false;
557 if (((
pulse[this_layer][this_wire] >> bx_time) & 1) == 1) {
559 if (hit_layer[this_layer] ==
false) {
560 hit_layer[this_layer] =
true;
566 if (layers_hit >= pretrig_thresh[i_pattern]) {
569 LogTrace(
"CSCAnodeLCTProcessor") <<
"Pretrigger was satisfied for wire: " << key_wire
570 <<
" pattern: " << i_pattern <<
" bx_time: " << bx_time;
593 unsigned int temp_quality;
594 int this_layer, this_wire, delta_wire;
597 const unsigned int nplanes_hit_pattern_acc =
601 const std::string ptn_label[] = {
"Accelerator",
"CollisionA",
"CollisionB"};
606 hit_layer[i_layer] =
false;
608 double num_pattern_hits = 0., times_sum = 0.;
609 std::multiset<int> mset_for_median;
610 mset_for_median.clear();
616 this_wire = delta_wire + key_wire;
623 if (hit_layer[this_layer] ==
false) {
626 hit_layer[this_layer] =
true;
629 <<
"bx_time: " <<
first_bx[key_wire] <<
" pattern: " << i_pattern <<
" keywire: " << key_wire
630 <<
" layer: " << this_layer <<
" quality: " << temp_quality;
634 if (
abs(delta_wire) < 2) {
638 for (
unsigned int dbx = 0; dbx <
hit_persist; dbx++) {
639 if (((
pulse[this_layer][this_wire] >> (first_bx_layer - 1)) & 1) == 1)
644 times_sum += (double)first_bx_layer;
645 num_pattern_hits += 1.;
646 mset_for_median.insert(first_bx_layer);
648 LogTrace(
"CSCAnodeLCTProcessor") <<
" 1st bx in layer: " << first_bx_layer <<
" sum bx: " << times_sum
649 <<
" #pat. hits: " << num_pattern_hits;
657 const int sz = mset_for_median.size();
659 std::multiset<int>::iterator im = mset_for_median.begin();
661 std::advance(im, sz / 2 - 1);
664 else if ((sz % 2) == 1)
669 #if defined(EDM_ML_DEBUG)
671 auto lt =
LogTrace(
"CSCAnodeLCTProcessor")
673 for (im = mset_for_median.begin(); im != mset_for_median.end(); im++) {
680 if (temp_quality >= pattern_thresh[i_pattern]) {
687 if (i_pattern == 0) {
689 quality[key_wire][0] = temp_quality;
692 if (static_cast<int>(temp_quality) >
quality[key_wire][1]) {
693 quality[key_wire][1] = temp_quality;
694 quality[key_wire][2] = i_pattern - 1;
698 LogTrace(
"CSCAnodeLCTProcessor") <<
"Pattern found; keywire: " << key_wire <<
" type: " << ptn_label[i_pattern]
699 <<
" quality: " << temp_quality <<
"\n";
705 LogTrace(
"CSCAnodeLCTProcessor") <<
"Collision Pattern A is chosen"
707 else if (
quality[key_wire][2] == 1)
708 LogTrace(
"CSCAnodeLCTProcessor") <<
"Collision Pattern B is chosen"
720 for (
int key_wire = 0; key_wire <
numWireGroups; key_wire++) {
721 for (
int i_pattern = 0; i_pattern < 2; i_pattern++) {
722 ghost_cleared[key_wire][i_pattern] = 0;
725 int qual_this =
quality[key_wire][i_pattern];
728 int qual_prev = (key_wire > 0) ?
quality[key_wire - 1][i_pattern] : 0;
738 if (qual_prev >= qual_this)
739 ghost_cleared[key_wire][i_pattern] = 1;
742 ghost_cleared[key_wire][i_pattern] = 1;
748 if (ghost_cleared[key_wire][i_pattern] == 1) {
751 << ((i_pattern == 0) ?
"Accelerator" :
"Collision") <<
" pattern ghost cancelled on key_wire "
752 << key_wire <<
" q=" << qual_this <<
" by wire " << key_wire - 1 <<
" q=" << qual_prev;
761 if (qual_next > qual_this)
762 ghost_cleared[key_wire][i_pattern] = 1;
765 ghost_cleared[key_wire][i_pattern] = 1;
768 if (ghost_cleared[key_wire][i_pattern] == 1) {
771 << ((i_pattern == 0) ?
"Accelerator" :
"Collision") <<
" pattern ghost cancelled on key_wire "
772 << key_wire <<
" q=" << qual_this <<
" by wire " << key_wire + 1 <<
" q=" << qual_next;
782 for (
int key_wire = 0; key_wire <
numWireGroups; key_wire++) {
783 for (
int i_pattern = 0; i_pattern < 2; i_pattern++) {
784 if (ghost_cleared[key_wire][i_pattern] > 0) {
785 clear(key_wire, i_pattern);
794 for (
int i_pattern = 0; i_pattern < 2; i_pattern++) {
795 ghost_cleared[i_pattern] = 0;
800 int qual_this =
quality[key_wire][i_pattern];
809 if (not(
p.getKeyWG() == key_wire - 1 and 1 -
p.getAccelerator() == i_pattern))
812 bool ghost_cleared_prev =
false;
813 int qual_prev =
p.getQuality();
814 int first_bx_prev =
p.getBX();
817 <<
"ghost concellation logic " << ((i_pattern == 0) ?
"Accelerator" :
"Collision") <<
" key_wire "
818 << key_wire <<
" quality " << qual_this <<
" bx " <<
first_bx[key_wire] <<
" previous key_wire "
819 << key_wire - 1 <<
" quality " << qual_prev <<
" bx " <<
first_bx[key_wire - 1];
830 if (qual_prev >= qual_this)
831 ghost_cleared[i_pattern] = 1;
832 else if (qual_prev < qual_this)
833 ghost_cleared_prev =
true;
836 ghost_cleared[i_pattern] = 1;
839 ghost_cleared_prev =
true;
842 if (ghost_cleared[i_pattern] == 1) {
845 << ((i_pattern == 0) ?
"Accelerator" :
"Collision") <<
" pattern ghost cancelled on key_wire "
846 << key_wire <<
" q=" << qual_this <<
" by wire " << key_wire - 1 <<
" q=" << qual_prev;
850 if (ghost_cleared_prev) {
853 << ((i_pattern == 0) ?
"Accelerator" :
"Collision") <<
" pattern ghost cancelled on key_wire "
854 << key_wire - 1 <<
" q=" << qual_prev <<
" by wire " << key_wire <<
" q=" << qual_this;
869 int n_alct_all = 0, n_alct = 0;
874 for (
const auto&
p : fourBest) {
880 <<
"C:" <<
theChamber <<
" all " << n_alct_all <<
" found " << n_alct;
885 for (
const auto&
p : fourBest) {
886 const int bx =
p.getBX();
891 <<
"; skipping it... +++\n";
947 LogTrace(
"CSCAnodeLCTProcessor") << all_alcts.size() <<
" ALCTs at the input of best-track selector: ";
948 for (
const auto&
p : all_alcts) {
957 for (
const auto&
p : all_alcts) {
969 int accel =
p.getAccelerator();
970 int qual =
p.getQuality();
971 int wire =
p.getKeyWG();
978 if (!vA || qual > qA || (qual == qA && wire > wA)) {
981 if (!vB || qual > qB || (qual == qB && wire < wB)) {
987 for (
int accel = 0; accel <= 1; accel++) {
989 if (tA[
bx][accel].isValid()) {
991 LogTrace(
"CSCAnodeLCTProcessor") <<
"tA: " << tA[
bx][accel];
992 LogTrace(
"CSCAnodeLCTProcessor") <<
"tB: " << tB[
bx][accel];
994 bestALCTs[
bx][accel] = tA[
bx][accel];
997 if (tA[
bx][accel] != tB[
bx][accel] && tA[
bx][accel].getQuality() == tB[
bx][accel].getQuality()) {
998 secondALCTs[
bx][accel] = tB[
bx][accel];
1004 for (
const auto&
p : all_alcts) {
1005 if (
p.isValid() &&
p.getAccelerator() == accel &&
p.getBX() ==
bx &&
1008 p.getKeyWG() >= secondALCTs[
bx][accel].
getKeyWG()) {
1009 secondALCTs[
bx][accel] =
p;
1018 std::vector<CSCALCTDigi> fourBest;
1021 if (bestALCTs[
bx][
i].isValid()) {
1022 fourBest.push_back(bestALCTs[
bx][
i]);
1026 if (secondALCTs[
bx][
i].isValid()) {
1027 fourBest.push_back(secondALCTs[
bx][
i]);
1033 LogTrace(
"CSCAnodeLCTProcessor") << fourBest.size() <<
" ALCTs selected: ";
1034 for (
const auto&
p : fourBest) {
1043 bool returnValue =
false;
1061 if (qual1 > qual2) {
1090 if (
quality[key_wire][1] > 0) {
1093 LogTrace(
"CSCAnodeLCTProcessor") <<
"trigMode(): collision track " << key_wire <<
" disabled"
1099 if (
quality[key_wire][0] > 0) {
1102 LogTrace(
"CSCAnodeLCTProcessor") <<
"trigMode(): accelerator track " << key_wire <<
" disabled"
1112 LogTrace(
"CSCAnodeLCTProcessor") <<
"trigMode(): collision track " << key_wire <<
" disabled"
1120 int promotionBit = 1 << 2;
1126 if (
quality[key_wire][0] > 0) {
1129 LogTrace(
"CSCAnodeLCTProcessor") <<
"alctMode(): accelerator track " << key_wire <<
" ignored"
1135 if (
quality[key_wire][1] > 0) {
1136 quality[key_wire][1] += promotionBit;
1138 LogTrace(
"CSCAnodeLCTProcessor") <<
"alctMode(): collision track " << key_wire <<
" promoted"
1144 if (
quality[key_wire][0] > 0) {
1145 quality[key_wire][0] += promotionBit;
1147 LogTrace(
"CSCAnodeLCTProcessor") <<
"alctMode(): accelerator track " << key_wire <<
" promoted"
1153 if (
quality[key_wire][1] > 0) {
1156 LogTrace(
"CSCAnodeLCTProcessor") <<
"alctMode(): collision track " << key_wire <<
" ignored"
1165 std::ostringstream strm;
1167 strm <<
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1168 strm <<
"+ ALCT configuration parameters: +\n";
1169 strm <<
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1170 strm <<
" fifo_tbins [total number of time bins in DAQ readout] = " <<
fifo_tbins <<
"\n";
1171 strm <<
" fifo_pretrig [start time of anode raw hits in DAQ readout] = " <<
fifo_pretrig <<
"\n";
1172 strm <<
" drift_delay [drift delay after pre-trigger, in 25 ns bins] = " <<
drift_delay <<
"\n";
1173 strm <<
" nplanes_hit_pretrig [min. number of layers hit for pre-trigger] = " <<
nplanes_hit_pretrig <<
"\n";
1174 strm <<
" nplanes_hit_pattern [min. number of layers hit for trigger] = " <<
nplanes_hit_pattern <<
"\n";
1175 strm <<
" nplanes_hit_accel_pretrig [min. number of layers hit for accel."
1177 strm <<
" nplanes_hit_accel_pattern [min. number of layers hit for accel."
1179 strm <<
" trig_mode [enabling/disabling collision/accelerator tracks] = " <<
trig_mode <<
"\n";
1180 strm <<
" accel_mode [preference to collision/accelerator tracks] = " <<
accel_mode <<
"\n";
1181 strm <<
" l1a_window_width [L1Accept window width, in 25 ns bins] = " <<
l1a_window_width <<
"\n";
1182 strm <<
"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
1183 LogDebug(
"CSCAnodeLCTProcessor") << strm.str();
1192 std::ostringstream strstrm;
1194 if (i_wire % 10 == 0) {
1196 strstrm << i_wire / 10;
1198 strstrm << (i_wire - 100) / 10;
1204 strstrm << i_wire % 10;
1209 if (!wire[i_layer][i_wire].
empty()) {
1210 std::vector<int> bx_times = wire[i_layer][i_wire];
1211 strstrm << std::hex << bx_times[0] <<
std::dec;
1217 LogTrace(
"CSCAnodeLCTProcessor") << strstrm.str();
1223 std::vector<CSCALCTDigi> tmpV;
1229 static std::atomic<int> late_tbins{
early_tbins + lct_bins};
1231 static std::atomic<int> ifois{0};
1235 <<
"+++ fifo_pretrig = " <<
fifo_pretrig <<
"; in-time ALCTs are not getting read-out!!! +++"
1242 <<
"+++ Allowed range of time bins, [0-" << late_tbins <<
"] exceeds max allowed, "
1244 <<
"+++ Set late_tbins to max allowed +++\n";
1252 const std::vector<CSCALCTDigi>& all_alcts =
getALCTs(nMaxALCTs);
1253 for (
const auto&
p : all_alcts) {
1261 LogDebug(
"CSCAnodeLCTProcessor") <<
" Do not report ALCT on keywire " <<
p.getKeyWG() <<
": found at bx " <<
bx
1262 <<
", whereas the earliest allowed bx is " <<
early_tbins + 1;
1267 if (
bx > late_tbins) {
1269 LogDebug(
"CSCAnodeLCTProcessor") <<
" Do not report ALCT on keywire " <<
p.getKeyWG() <<
": found at bx " <<
bx
1270 <<
", whereas the latest allowed bx is " << late_tbins;
1283 for (
auto&
p : tmpV) {
1291 std::vector<CSCALCTDigi> tmpV;
1319 std::ostringstream strstrm_header;
1320 LogTrace(
"CSCAnodeLCTProcessor") <<
"\n"
1321 <<
"Pattern: " << i_pattern <<
" Key wire: " << key_wire;
1322 for (
int i = 1;
i <= 32;
i++) {
1323 strstrm_header << ((32 -
i) % 10);
1325 LogTrace(
"CSCAnodeLCTProcessor") << strstrm_header.str();
1328 std::ostringstream strstrm_pulse;
1332 for (
int i = 1;
i <= 32;
i++) {
1333 strstrm_pulse << ((
pulse[this_layer][this_wire] >> (32 -
i)) & 1);
1336 << strstrm_pulse.str() <<
" on layer " << this_layer <<
" wire " << this_wire;
1340 LogTrace(
"CSCAnodeLCTProcessor") <<
"-------------------------------------------";
1346 if (temp_quality > 3)
1347 Q = temp_quality - 3;