File indexing completed on 2025-12-17 09:19:47
0001 #include "SingleMicromegasPoolInput_v1.h"
0002
0003 #include "Fun4AllStreamingInputManager.h"
0004 #include "InputManagerType.h"
0005
0006 #include <ffarawobjects/MicromegasRawHitContainerv3.h>
0007 #include <ffarawobjects/MicromegasRawHitv3.h>
0008
0009 #include <fun4all/Fun4AllHistoManager.h>
0010 #include <qautils/QAHistManagerDef.h>
0011 #include <qautils/QAUtil.h>
0012
0013 #include <phool/PHCompositeNode.h>
0014 #include <phool/PHNodeIterator.h> // for PHNodeIterator
0015 #include <phool/getClass.h>
0016 #include <phool/phool.h>
0017
0018 #include <Event/Event.h>
0019 #include <Event/EventTypes.h>
0020 #include <Event/Eventiterator.h>
0021 #include <Event/fileEventiterator.h>
0022
0023 #include <TFile.h>
0024 #include <TH1.h>
0025
0026 #include <algorithm>
0027 #include <bitset>
0028
0029 namespace
0030 {
0031
0032
0033 static constexpr uint16_t m_adc_invalid = 65000;
0034
0035
0036 static constexpr int m_npackets_active = 2;
0037
0038
0039 static constexpr int m_min_req_samples = 5;
0040
0041
0042 enum SampaDataType
0043 {
0044 HEARTBEAT_T = 0b000,
0045 TRUNCATED_DATA_T = 0b001,
0046 TRUNCATED_TRIG_EARLY_DATA_T = 0b011,
0047 NORMAL_DATA_T = 0b100,
0048 LARGE_DATA_T = 0b101,
0049 TRIG_EARLY_DATA_T = 0b110,
0050 TRIG_EARLY_LARGE_DATA_T = 0b111,
0051 };
0052
0053 }
0054
0055
0056 SingleMicromegasPoolInput_v1::SingleMicromegasPoolInput_v1(const std::string& name)
0057 : SingleStreamingInput(name)
0058 {
0059 SubsystemEnum(InputManagerType::MICROMEGAS);
0060 m_rawHitContainerName = "MICROMEGASRAWHIT";
0061 }
0062
0063
0064 SingleMicromegasPoolInput_v1::~SingleMicromegasPoolInput_v1()
0065 {
0066
0067 std::cout << "SingleMicromegasPoolInput_v1::~SingleMicromegasPoolInput_v1 - runnumber: " << RunNumber() << std::endl;
0068
0069
0070 m_timer.print_stat();
0071
0072 for( const auto& [packet,counts]:m_waveform_count_total )
0073 {
0074 const auto dropped_bco = m_waveform_count_dropped_bco[packet];
0075 const auto dropped_pool = m_waveform_count_dropped_pool[packet];
0076 std::cout << "SingleMicromegasPoolInput_v1::~SingleMicromegasPoolInput_v1 -"
0077 << " packet: " << packet
0078 << " wf_total: " << counts
0079 << " wf_dropped_bco: " << dropped_bco
0080 << " wf_dropped_pool: " << dropped_pool
0081 << " ratio_bco: " << double(dropped_bco)/counts
0082 << " ratio_pool: " << double(dropped_pool)/counts
0083 << std::endl;
0084 }
0085 std::cout << std::endl;
0086
0087
0088 for( const auto& [fee,counts]:m_fee_waveform_count_total )
0089 {
0090 const auto dropped_bco = m_fee_waveform_count_dropped_bco[fee];
0091 std::cout << "SingleMicromegasPoolInput_v1::~SingleMicromegasPoolInput_v1 -"
0092 << " fee: " << fee
0093 << " wf_total: " << counts
0094 << " wf_dropped_bco: " << dropped_bco
0095 << " ratio_bco: " << double(dropped_bco)/counts
0096 << std::endl;
0097
0098 }
0099 std::cout << std::endl;
0100
0101
0102 for( const auto& [packet_id, bco_matching]:m_bco_matching_information_map )
0103 {
0104 const auto old_precision = std::cout.precision();
0105 std::cout << "SingleMicromegasPoolInput_v1::~SingleMicromegasPoolInput_v1 -"
0106 << " packet: " << packet_id
0107 << " multiplier: " << std::setprecision(9) << bco_matching.get_adjusted_multiplier() << std::setprecision(old_precision)
0108 << std::endl;
0109 }
0110
0111 }
0112
0113
0114 void SingleMicromegasPoolInput_v1::FillPool(const unsigned int )
0115 {
0116 if (AllDone())
0117 {
0118 return;
0119 }
0120
0121 while (!GetEventiterator())
0122 {
0123 if (!OpenNextFile())
0124 {
0125 AllDone(1);
0126 return;
0127 }
0128 }
0129
0130 while (GetSomeMoreEvents())
0131 {
0132 std::unique_ptr<Event> evt(GetEventiterator()->getNextEvent());
0133 while (!evt)
0134 {
0135 fileclose();
0136 if (!OpenNextFile())
0137 {
0138 AllDone(1);
0139 return;
0140 }
0141
0142
0143 evt.reset(GetEventiterator()->getNextEvent());
0144 }
0145
0146 if (Verbosity() > 2)
0147 {
0148 std::cout << "Fetching next Event" << evt->getEvtSequence() << std::endl;
0149 }
0150
0151 if (evt->getEvtType() != DATAEVENT)
0152 {
0153 m_NumSpecialEvents++;
0154 continue;
0155 }
0156
0157 RunNumber(evt->getRunNumber());
0158 if (Verbosity() > 1)
0159 {
0160 evt->identify();
0161 }
0162
0163 const int EventSequence = evt->getEvtSequence();
0164 const int npackets = evt->getPacketList(&plist[0], 10);
0165
0166 if (npackets == 10)
0167 {
0168 std::cout << "SingleMicromegasPoolInput_v1::FillPool - too many packets" << std::endl;
0169 exit(1);
0170 }
0171
0172 for (int i = 0; i < npackets; i++)
0173 {
0174
0175 std::unique_ptr<Packet> packet(plist[i]);
0176
0177
0178 const auto packet_id = packet->getIdentifier();
0179
0180 if (Verbosity() > 1)
0181 {
0182 packet->identify();
0183 }
0184
0185
0186 auto& bco_matching_information = m_bco_matching_information_map[packet_id];
0187 bco_matching_information.set_verbosity(Verbosity());
0188
0189
0190 bco_matching_information.save_gtm_bco_information(packet.get());
0191
0192
0193 const int n_tagger = packet->lValue(0, "N_TAGGER");
0194 for (int t = 0; t < n_tagger; ++t)
0195 {
0196 const bool is_lvl1 = static_cast<uint8_t>(packet->lValue(t, "IS_LEVEL1_TRIGGER"));
0197 const bool is_endat = static_cast<uint8_t>(packet->lValue(t, "IS_ENDAT"));
0198 if (is_lvl1||is_endat)
0199 {
0200 const uint64_t gtm_bco = static_cast<uint64_t>(packet->lValue(t, "BCO"));
0201 m_BeamClockPacket[gtm_bco].insert(packet_id);
0202 m_BclkStack.insert(gtm_bco);
0203 }
0204 }
0205
0206
0207 const int nwf = packet->iValue(0, "NR_WF");
0208
0209
0210 m_waveform_count_total[packet_id] += nwf;
0211 h_waveform_count_total->Fill( std::to_string(packet_id).c_str(), nwf );
0212
0213 if (Verbosity())
0214 {
0215 std::cout
0216 << "SingleMicromegasPoolInput_v1::FillPool -"
0217 << " packet: " << packet_id
0218 << " n_waveform: " << nwf
0219 << std::endl;
0220 bco_matching_information.print_gtm_bco_information();
0221 }
0222
0223
0224
0225
0226
0227
0228 bco_matching_information.find_reference_from_modebits(packet.get());
0229
0230
0231 if (!bco_matching_information.is_verified())
0232 {
0233 bco_matching_information.find_reference_from_data(packet.get());
0234 }
0235
0236
0237 if (!bco_matching_information.is_verified())
0238 {
0239 std::cout << "SingleMicromegasPoolInput_v1::FillPool - bco_matching not verified, dropping packet" << std::endl;
0240 m_waveform_count_dropped_bco[packet_id] += nwf;
0241 h_waveform_count_dropped_bco->Fill( std::to_string(packet_id).c_str(), nwf );
0242 continue;
0243 }
0244
0245 for (int wf = 0; wf < nwf; wf++)
0246 {
0247
0248 const int fee_id = packet->iValue(wf, "FEE");
0249 ++m_fee_waveform_count_total[fee_id];
0250
0251
0252 const auto checksum_error = packet->iValue(wf, "CHECKSUMERROR");
0253 if (checksum_error)
0254 {
0255 continue;
0256 }
0257
0258
0259 const unsigned int fee_bco = packet->iValue(wf, "BCO");
0260
0261
0262 uint64_t gtm_bco = 0;
0263 const auto result = bco_matching_information.find_gtm_bco(fee_bco);
0264
0265 if (result)
0266 {
0267
0268 gtm_bco = result.value();
0269 }
0270 else
0271 {
0272
0273 ++m_waveform_count_dropped_bco[packet_id];
0274 ++m_fee_waveform_count_dropped_bco[fee_id];
0275 h_waveform_count_dropped_bco->Fill( std::to_string(packet_id).c_str(), 1 );
0276
0277
0278 continue;
0279 }
0280
0281
0282
0283 if( packet->iValue(wf, "TYPE" ) == HEARTBEAT_T ) continue;
0284
0285
0286 const uint16_t samples = packet->iValue(wf, "SAMPLES");
0287 if (samples < m_min_req_samples)
0288 {
0289 continue;
0290 }
0291
0292
0293 auto newhit = std::make_unique<MicromegasRawHitv3>();
0294 newhit->set_bco(fee_bco);
0295 newhit->set_gtm_bco(gtm_bco);
0296
0297
0298 newhit->set_packetid(packet_id);
0299 newhit->set_fee(fee_id);
0300 newhit->set_channel(packet->iValue(wf, "CHANNEL"));
0301 newhit->set_sampaaddress(packet->iValue(wf, "SAMPAADDRESS"));
0302 newhit->set_sampachannel(packet->iValue(wf, "CHANNEL"));
0303
0304
0305 for (uint16_t is = 0; is < samples; ++is)
0306 {
0307 uint16_t adc = packet->iValue(wf, is);
0308 if( adc == m_adc_invalid)
0309 {
0310 continue;
0311 }
0312
0313 uint16_t first = is;
0314 MicromegasRawHitv3::adc_list_t values;
0315 for( ;is<samples && (adc = packet->iValue(wf, is)) != m_adc_invalid; ++is )
0316 { values.push_back(adc); }
0317 newhit->move_adc_waveform( first, std::move(values));
0318
0319 }
0320
0321 m_BeamClockFEE[gtm_bco].insert(fee_id);
0322 m_FEEBclkMap[fee_id] = gtm_bco;
0323 if (Verbosity() > 2)
0324 {
0325 std::cout << "evtno: " << EventSequence
0326 << ", hits: " << wf
0327 << ", num waveforms: " << nwf
0328 << ", bco: 0x" << std::hex << gtm_bco << std::dec
0329 << ", FEE: " << fee_id << std::endl;
0330 }
0331
0332 if (StreamingInputManager())
0333 {
0334 StreamingInputManager()->AddMicromegasRawHit(gtm_bco, newhit.get());
0335 }
0336
0337 m_MicromegasRawHitMap[gtm_bco].push_back(newhit.release());
0338 }
0339 }
0340 }
0341 }
0342
0343
0344 void SingleMicromegasPoolInput_v1::Print(const std::string& what) const
0345 {
0346 if (what == "ALL" || what == "FEE")
0347 {
0348 for (const auto& bcliter : m_BeamClockFEE)
0349 {
0350 std::cout << "Beam clock 0x" << std::hex << bcliter.first << std::dec << std::endl;
0351 for (auto feeiter : bcliter.second)
0352 {
0353 std::cout << "FEM: " << feeiter << std::endl;
0354 }
0355 }
0356 }
0357
0358 if (what == "ALL" || what == "FEEBCLK")
0359 {
0360 for (auto bcliter : m_FEEBclkMap)
0361 {
0362 std::cout << "FEE" << bcliter.first << " bclk: 0x"
0363 << std::hex << bcliter.second << std::dec << std::endl;
0364 }
0365 }
0366
0367 if (what == "ALL" || what == "STORAGE")
0368 {
0369 for (const auto& bcliter : m_MicromegasRawHitMap)
0370 {
0371 std::cout << "Beam clock 0x" << std::hex << bcliter.first << std::dec << std::endl;
0372 for (auto feeiter : bcliter.second)
0373 {
0374 std::cout
0375 << "fee: " << feeiter->get_fee()
0376 << " at " << std::hex << feeiter << std::dec
0377 << std::endl;
0378 }
0379 }
0380 }
0381
0382 if (what == "ALL" || what == "STACK")
0383 {
0384 for (const auto& iter : m_BclkStack)
0385 {
0386 std::cout << "stacked bclk: 0x" << std::hex << iter << std::dec << std::endl;
0387 }
0388 }
0389 }
0390
0391
0392 void SingleMicromegasPoolInput_v1::CleanupUsedPackets(const uint64_t bclk, bool dropped)
0393 {
0394
0395
0396 for(auto iter = m_MicromegasRawHitMap.begin(); iter != m_MicromegasRawHitMap.end() && (iter->first <= bclk); iter = m_MicromegasRawHitMap.erase(iter))
0397 {
0398 for (const auto& rawhit : iter->second)
0399 {
0400 if( dropped )
0401 {
0402
0403 ++m_waveform_count_dropped_pool[rawhit->get_packetid()];
0404 h_waveform_count_dropped_pool->Fill( std::to_string(rawhit->get_packetid()).c_str(), 1 );
0405 }
0406 delete rawhit;
0407 }
0408 }
0409
0410
0411
0412 m_BclkStack.erase(m_BclkStack.begin(), m_BclkStack.upper_bound(bclk));
0413 m_BeamClockFEE.erase(m_BeamClockFEE.begin(), m_BeamClockFEE.upper_bound(bclk));
0414 m_BeamClockPacket.erase(m_BeamClockPacket.begin(), m_BeamClockPacket.upper_bound(bclk));
0415
0416
0417 for( auto&& bco_matching:m_bco_matching_information_map )
0418 { bco_matching.second.cleanup(bclk); }
0419
0420 }
0421
0422
0423 void SingleMicromegasPoolInput_v1::ClearCurrentEvent()
0424 {
0425 std::cout << "SingleMicromegasPoolInput_v1::ClearCurrentEvent." << std::endl;
0426 uint64_t currentbclk = *m_BclkStack.begin();
0427 CleanupUsedPackets(currentbclk);
0428 return;
0429 }
0430
0431
0432 bool SingleMicromegasPoolInput_v1::GetSomeMoreEvents()
0433 {
0434 if (AllDone())
0435 {
0436 return false;
0437 }
0438
0439
0440 if (m_MicromegasRawHitMap.size() < m_BcoPoolSize)
0441 {
0442 return true;
0443 }
0444
0445
0446 std::set<int> toerase;
0447 uint64_t lowest_bclk = m_MicromegasRawHitMap.begin()->first + m_BcoRange;
0448 for (auto bcliter : m_FEEBclkMap)
0449 {
0450 if (bcliter.second <= lowest_bclk)
0451 {
0452 uint64_t highest_bclk = m_MicromegasRawHitMap.rbegin()->first;
0453 if ((highest_bclk - m_MicromegasRawHitMap.begin()->first) < MaxBclkDiff())
0454 {
0455 return true;
0456 }
0457 else
0458 {
0459 std::cout << PHWHERE << Name() << ": erasing FEE " << bcliter.first
0460 << " with stuck bclk: " << std::hex << bcliter.second
0461 << " current bco range: 0x" << m_MicromegasRawHitMap.begin()->first
0462 << ", to: 0x" << highest_bclk << ", delta: " << std::dec
0463 << (highest_bclk - m_MicromegasRawHitMap.begin()->first)
0464 << std::dec << std::endl;
0465 toerase.insert(bcliter.first);
0466 }
0467 }
0468 }
0469 for(auto& fee: toerase)
0470 {
0471 m_FEEBclkMap.erase(fee);
0472 }
0473
0474 return false;
0475 }
0476
0477
0478 void SingleMicromegasPoolInput_v1::CreateDSTNode(PHCompositeNode* topNode)
0479 {
0480 PHNodeIterator iter(topNode);
0481 auto dstNode = dynamic_cast<PHCompositeNode*>(iter.findFirst("PHCompositeNode", "DST"));
0482 if (!dstNode)
0483 {
0484 dstNode = new PHCompositeNode("DST");
0485 topNode->addNode(dstNode);
0486 }
0487
0488 PHNodeIterator iterDst(dstNode);
0489 auto detNode = dynamic_cast<PHCompositeNode*>(iterDst.findFirst("PHCompositeNode", "MICROMEGAS"));
0490 if (!detNode)
0491 {
0492 detNode = new PHCompositeNode("MICROMEGAS");
0493 dstNode->addNode(detNode);
0494 }
0495
0496 auto container = findNode::getClass<MicromegasRawHitContainer>(detNode, m_rawHitContainerName);
0497 if (!container)
0498 {
0499 container = new MicromegasRawHitContainerv3();
0500 auto newNode = new PHIODataNode<PHObject>(container, m_rawHitContainerName, "PHObject");
0501 detNode->addNode(newNode);
0502 }
0503 }
0504
0505
0506 void SingleMicromegasPoolInput_v1::ConfigureStreamingInputManager()
0507 {
0508 if (StreamingInputManager())
0509 {
0510 StreamingInputManager()->SetMicromegasBcoRange(m_BcoRange);
0511 StreamingInputManager()->SetMicromegasNegativeBco(m_NegativeBco);
0512 }
0513 }
0514
0515
0516 void SingleMicromegasPoolInput_v1::FillBcoQA(uint64_t gtm_bco)
0517 {
0518 auto hm = QAHistManagerDef::getHistoManager();
0519 assert(hm);
0520
0521
0522 unsigned int n_waveforms = 0;
0523 std::set<int> found_packets;
0524 for (uint64_t gtm_bco_loc = gtm_bco - m_NegativeBco; gtm_bco_loc < gtm_bco + m_BcoRange - m_NegativeBco; ++gtm_bco_loc)
0525 {
0526
0527 const auto packet_iter = m_BeamClockPacket.find(gtm_bco_loc);
0528 if( packet_iter != m_BeamClockPacket.end() )
0529 { found_packets.insert( packet_iter->second.begin(), packet_iter->second.end() ); }
0530
0531
0532 const auto wf_iter = m_MicromegasRawHitMap.find(gtm_bco_loc);
0533 if (wf_iter != m_MicromegasRawHitMap.end())
0534 { n_waveforms += wf_iter->second.size(); }
0535 }
0536
0537
0538 h_packet_stat->Fill( "Reference", 1 );
0539
0540 for( const auto& packet_id:found_packets )
0541 { h_packet_stat->Fill( std::to_string(packet_id).c_str(), 1 ); }
0542 h_packet_stat->Fill( "All", found_packets.size()>= m_npackets_active );
0543
0544
0545 h_packet->Fill(found_packets.size());
0546
0547
0548 h_waveform->Fill(n_waveforms);
0549 }
0550
0551 void SingleMicromegasPoolInput_v1::createQAHistos()
0552 {
0553 auto hm = QAHistManagerDef::getHistoManager();
0554 assert(hm);
0555
0556
0557 h_packet = new TH1I( "h_MicromegasBCOQA_npacket_bco", "TPOT Packet Count per GTM BCO; Matching BCO tagger count; GL1 trigger count", 10, 0, 10 );
0558
0559
0560 h_waveform = new TH1I( "h_MicromegasBCOQA_nwaveform_bco", "TPOT Waveform Count per GTM BCO; Matching Waveform count; GL1 trigger count", 4100, 0, 4100 );
0561
0562
0563
0564
0565
0566
0567 h_packet_stat = new TH1I( "h_MicromegasBCOQA_packet_stat", "Matching Tagger count per packet; packet id; GL1 trigger count", m_npackets_active+2, 0, m_npackets_active+2 );
0568 h_packet_stat->GetXaxis()->SetBinLabel(1, "Reference" );
0569 h_packet_stat->GetXaxis()->SetBinLabel(2, "5001" );
0570 h_packet_stat->GetXaxis()->SetBinLabel(3, "5002" );
0571 h_packet_stat->GetXaxis()->SetBinLabel(4, "All" );
0572 h_packet_stat->GetYaxis()->SetTitle( "trigger count" );
0573
0574
0575 h_waveform_count_total = new TH1I( "h_MicromegasBCOQA_waveform_count_total", "Total number of waveforms per packet", m_npackets_active, 0, m_npackets_active );
0576
0577
0578 h_waveform_count_dropped_bco = new TH1I( "h_MicromegasBCOQA_waveform_count_dropped_bco", "Number of dropped waveforms per packet (bco)", m_npackets_active, 0, m_npackets_active );
0579
0580
0581 h_waveform_count_dropped_pool = new TH1I( "h_MicromegasBCOQA_waveform_count_dropped_pool", "Number of dropped waveforms per packet (pool)", m_npackets_active, 0, m_npackets_active );
0582
0583
0584 for( const auto& h:std::initializer_list<TH1*>{h_waveform_count_total, h_waveform_count_dropped_bco, h_waveform_count_dropped_pool} )
0585 {
0586 h->GetXaxis()->SetBinLabel(1, "5001" );
0587 h->GetXaxis()->SetBinLabel(2, "5002" );
0588 h->GetYaxis()->SetTitle( "waveform count" );
0589 h->GetXaxis()->SetTitle( "packet id" );
0590 }
0591
0592
0593 for( const auto& h:std::initializer_list<TH1*>{h_packet, h_waveform, h_packet_stat, h_waveform_count_total, h_waveform_count_dropped_bco, h_waveform_count_dropped_pool} )
0594 {
0595 h->SetFillStyle(1001);
0596 h->SetFillColor(kYellow);
0597 hm->registerHisto(h);
0598 }
0599 }