File indexing completed on 2025-08-06 08:17:32
0001 #include "CaloTowerBuilder.h"
0002 #include "CaloTowerDefs.h"
0003
0004 #include <calobase/TowerInfo.h>
0005 #include <calobase/TowerInfoContainer.h>
0006 #include <calobase/TowerInfoContainerSimv1.h>
0007 #include <calobase/TowerInfoContainerSimv2.h>
0008 #include <calobase/TowerInfoContainerv1.h>
0009 #include <calobase/TowerInfoContainerv2.h>
0010 #include <calobase/TowerInfoContainerv3.h>
0011 #include <calobase/TowerInfoContainerv4.h>
0012
0013 #include <ffarawobjects/CaloPacket.h>
0014 #include <ffarawobjects/CaloPacketContainer.h>
0015
0016 #include <fun4all/Fun4AllReturnCodes.h>
0017 #include <fun4all/SubsysReco.h> // for SubsysReco
0018 #include <phool/recoConsts.h>
0019
0020 #include <phool/PHCompositeNode.h>
0021 #include <phool/PHIODataNode.h> // for PHIODataNode
0022 #include <phool/PHNode.h> // for PHNode
0023 #include <phool/PHNodeIterator.h> // for PHNodeIterator
0024 #include <phool/PHObject.h> // for PHObject
0025 #include <phool/getClass.h>
0026
0027 #include <cdbobjects/CDBTTree.h> // for CDBTTree
0028
0029 #include <ffamodules/CDBInterface.h>
0030
0031 #include <Event/Event.h>
0032 #include <Event/EventTypes.h>
0033 #include <Event/packet.h>
0034
0035 #include <TSystem.h>
0036
0037 #include <climits>
0038 #include <iostream> // for operator<<, endl, basic...
0039 #include <memory> // for allocator_traits<>::val...
0040 #include <variant>
0041 #include <vector> // for vector
0042
0043 static const std::map<CaloTowerDefs::DetectorSystem, std::string> nodemap{
0044 {CaloTowerDefs::CEMC, "CEMCPackets"},
0045 {CaloTowerDefs::HCALIN, "HCALPackets"},
0046 {CaloTowerDefs::HCALOUT, "HCALPackets"},
0047 {CaloTowerDefs::ZDC, "ZDCPackets"},
0048 {CaloTowerDefs::SEPD, "SEPDPackets"}};
0049
0050 CaloTowerBuilder::CaloTowerBuilder(const std::string &name)
0051 : SubsysReco(name)
0052 , WaveformProcessing(new CaloWaveformProcessing())
0053 {
0054 }
0055
0056
0057 CaloTowerBuilder::~CaloTowerBuilder()
0058 {
0059 delete cdbttree;
0060 delete cdbttree_tbt_zs;
0061 delete WaveformProcessing;
0062 }
0063
0064
0065 int CaloTowerBuilder::InitRun(PHCompositeNode *topNode)
0066 {
0067 WaveformProcessing->set_processing_type(_processingtype);
0068 WaveformProcessing->set_softwarezerosuppression(m_bdosoftwarezerosuppression, m_nsoftwarezerosuppression);
0069 if (m_setTimeLim)
0070 {
0071 WaveformProcessing->set_timeFitLim(m_timeLim_low, m_timeLim_high);
0072 }
0073 if (m_dobitfliprecovery)
0074 {
0075 WaveformProcessing->set_bitFlipRecovery(m_dobitfliprecovery);
0076 }
0077
0078 if (m_dettype == CaloTowerDefs::CEMC)
0079 {
0080 m_detector = "CEMC";
0081 m_packet_low = 6001;
0082 m_packet_high = 6128;
0083 m_nchannels = 192;
0084 WaveformProcessing->set_template_name("CEMC_TEMPLATE");
0085 if (_processingtype == CaloWaveformProcessing::NONE)
0086 {
0087 WaveformProcessing->set_processing_type(CaloWaveformProcessing::TEMPLATE);
0088 }
0089
0090
0091
0092
0093
0094 m_calibName = "cemc_adcskipmask";
0095
0096 m_fieldname = "adcskipmask";
0097
0098 calibdir = CDBInterface::instance()->getUrl(m_calibName);
0099 if (calibdir.empty())
0100 {
0101 std::cout << PHWHERE << "ADC Skip mask not found in CDB, not even in the default... " << std::endl;
0102 exit(1);
0103 }
0104 cdbttree = new CDBTTree(calibdir);
0105 }
0106 else if (m_dettype == CaloTowerDefs::HCALIN)
0107 {
0108 m_packet_low = 7001;
0109 m_packet_high = 7008;
0110 m_detector = "HCALIN";
0111 m_nchannels = 192;
0112 WaveformProcessing->set_template_name("IHCAL_TEMPLATE");
0113 if (_processingtype == CaloWaveformProcessing::NONE)
0114 {
0115 WaveformProcessing->set_processing_type(CaloWaveformProcessing::TEMPLATE);
0116 }
0117 }
0118 else if (m_dettype == CaloTowerDefs::HCALOUT)
0119 {
0120 m_detector = "HCALOUT";
0121 m_packet_low = 8001;
0122 m_packet_high = 8008;
0123 m_nchannels = 192;
0124 WaveformProcessing->set_template_name("OHCAL_TEMPLATE");
0125 if (_processingtype == CaloWaveformProcessing::NONE)
0126 {
0127 WaveformProcessing->set_processing_type(CaloWaveformProcessing::TEMPLATE);
0128 }
0129 }
0130 else if (m_dettype == CaloTowerDefs::SEPD)
0131 {
0132 m_detector = "SEPD";
0133 m_packet_low = 9001;
0134 m_packet_high = 9006;
0135 m_nchannels = 128;
0136 WaveformProcessing->set_template_name("SEPD_TEMPLATE");
0137 if (_processingtype == CaloWaveformProcessing::NONE)
0138 {
0139 WaveformProcessing->set_processing_type(CaloWaveformProcessing::TEMPLATE);
0140 }
0141
0142 m_calibName = "SEPD_CHANNELMAP2";
0143 m_fieldname = "epd_channel_map2";
0144
0145 calibdir = CDBInterface::instance()->getUrl(m_calibName);
0146
0147 if (calibdir.empty())
0148 {
0149 std::cout << PHWHERE << "No sEPD mapping file for domain " << m_calibName << " found" << std::endl;
0150 exit(1);
0151 }
0152
0153 cdbttree_sepd_map = new CDBTTree(calibdir);
0154 }
0155 else if (m_dettype == CaloTowerDefs::ZDC)
0156 {
0157 m_detector = "ZDC";
0158 m_packet_low = 12001;
0159 m_packet_high = 12001;
0160 m_nchannels = 128;
0161 if (_processingtype == CaloWaveformProcessing::NONE)
0162 {
0163 WaveformProcessing->set_processing_type(CaloWaveformProcessing::FAST);
0164 }
0165 }
0166 WaveformProcessing->initialize_processing();
0167 if (m_dotbtszs)
0168 {
0169 cdbttree_tbt_zs = new CDBTTree(m_zsURL);
0170 }
0171
0172 CreateNodeTree(topNode);
0173 return Fun4AllReturnCodes::EVENT_OK;
0174 }
0175
0176 int CaloTowerBuilder::process_sim()
0177 {
0178 std::vector<std::vector<float>> waveforms;
0179
0180 for (int ich = 0; ich < (int) m_CalowaveformContainer->size(); ich++)
0181 {
0182 TowerInfo *towerinfo = m_CalowaveformContainer->get_tower_at_channel(ich);
0183 std::vector<float> waveform;
0184 waveform.reserve(m_nsamples);
0185 bool fillwaveform = true;
0186
0187 if (m_dotbtszs)
0188 {
0189 unsigned int key = m_CalowaveformContainer->encode_key(ich);
0190 int zs_threshold = cdbttree_tbt_zs->GetIntValue(key, m_zs_fieldname);
0191 int pre = towerinfo->get_waveform_value(0);
0192
0193 int post = towerinfo->get_waveform_value(6);
0194 if ((post - pre) <= zs_threshold)
0195 {
0196
0197 fillwaveform = false;
0198 waveform.push_back(pre);
0199 waveform.push_back(post);
0200 }
0201 }
0202 if (fillwaveform)
0203 {
0204 for (int samp = 0; samp < m_nsamples; samp++)
0205 {
0206 waveform.push_back(towerinfo->get_waveform_value(samp));
0207 }
0208 }
0209 waveforms.push_back(waveform);
0210 waveform.clear();
0211 }
0212
0213 std::vector<std::vector<float>> processed_waveforms = WaveformProcessing->process_waveform(waveforms);
0214 int n_channels = processed_waveforms.size();
0215 for (int i = 0; i < n_channels; i++)
0216 {
0217
0218 TowerInfo *towerwaveform = m_CalowaveformContainer->get_tower_at_channel(i);
0219 TowerInfo *towerinfo = m_CaloInfoContainer->get_tower_at_channel(i);
0220 towerinfo->copy_tower(towerwaveform);
0221 towerinfo->set_time(processed_waveforms.at(i).at(1));
0222 towerinfo->set_energy(processed_waveforms.at(i).at(0));
0223 towerinfo->set_time_float(processed_waveforms.at(i).at(1));
0224 towerinfo->set_pedestal(processed_waveforms.at(i).at(2));
0225 towerinfo->set_chi2(processed_waveforms.at(i).at(3));
0226 bool SZS = isSZS(processed_waveforms.at(i).at(1), processed_waveforms.at(i).at(3));
0227 if (processed_waveforms.at(i).at(4) == 0)
0228 {
0229 towerinfo->set_isRecovered(false);
0230 }
0231 else
0232 {
0233 towerinfo->set_isRecovered(true);
0234 }
0235 int n_samples = waveforms.at(i).size();
0236 if (n_samples == m_nzerosuppsamples || SZS)
0237 {
0238 towerinfo->set_isZS(true);
0239 }
0240 for (int j = 0; j < n_samples; j++)
0241 {
0242 towerinfo->set_waveform_value(j, waveforms.at(i).at(j));
0243 if (std::round(waveforms.at(i).at(j)) >= m_saturation)
0244 {
0245 towerinfo->set_isSaturated(true);
0246 }
0247 }
0248 }
0249 waveforms.clear();
0250
0251 return Fun4AllReturnCodes::EVENT_OK;
0252 }
0253
0254 int CaloTowerBuilder::process_data(PHCompositeNode *topNode, std::vector<std::vector<float>> &waveforms)
0255 {
0256 std::variant<CaloPacketContainer *, Event *> event;
0257 if (m_UseOfflinePacketFlag)
0258 {
0259 CaloPacketContainer *calopacketcontainer = findNode::getClass<CaloPacketContainer>(topNode, nodemap.find(m_dettype)->second);
0260 if (!calopacketcontainer)
0261 {
0262 for (int pid = m_packet_low; pid <= m_packet_high; pid++)
0263 {
0264 if (findNode::getClass<CaloPacket>(topNode, pid))
0265 {
0266 m_PacketNodesFlag = true;
0267 break;
0268 }
0269 }
0270 if (!m_PacketNodesFlag)
0271 {
0272 return Fun4AllReturnCodes::EVENT_OK;
0273 }
0274 }
0275 else
0276 {
0277 event = calopacketcontainer;
0278 }
0279 }
0280 else
0281 {
0282 Event *_event = findNode::getClass<Event>(topNode, "PRDF");
0283 if (_event == nullptr)
0284 {
0285 std::cout << PHWHERE << " Event not found" << std::endl;
0286 return Fun4AllReturnCodes::ABORTEVENT;
0287 }
0288 if (_event->getEvtType() != DATAEVENT)
0289 {
0290 return Fun4AllReturnCodes::ABORTEVENT;
0291 }
0292 event = _event;
0293 }
0294
0295 auto process_packet = [&](auto *packet, int pid)
0296 {
0297 if (packet)
0298 {
0299 int nchannels = packet->iValue(0, "CHANNELS");
0300 unsigned int adc_skip_mask = 0;
0301
0302 if (m_dettype == CaloTowerDefs::CEMC)
0303 {
0304 adc_skip_mask = cdbttree->GetIntValue(pid, m_fieldname);
0305 }
0306 if (m_dettype == CaloTowerDefs::ZDC)
0307 {
0308 nchannels = m_nchannels;
0309 }
0310 if (nchannels > m_nchannels)
0311 {
0312 return Fun4AllReturnCodes::ABORTEVENT;
0313 }
0314
0315 int n_pad_skip_mask = 0;
0316 for (int channel = 0; channel < nchannels; channel++)
0317 {
0318 if (skipChannel(channel, pid))
0319 {
0320 continue;
0321 }
0322 if (m_dettype == CaloTowerDefs::CEMC)
0323 {
0324 if (channel % 64 == 0)
0325 {
0326 unsigned int adcboard = (unsigned int) channel / 64;
0327 if ((adc_skip_mask >> adcboard) & 0x1U)
0328 {
0329 for (int iskip = 0; iskip < 64; iskip++)
0330 {
0331 n_pad_skip_mask++;
0332 std::vector<float> waveform;
0333 waveform.reserve(m_nsamples);
0334
0335 for (int samp = 0; samp < m_nzerosuppsamples; samp++)
0336 {
0337 waveform.push_back(0);
0338 }
0339 waveforms.push_back(waveform);
0340 waveform.clear();
0341 }
0342 }
0343 }
0344 }
0345
0346 std::vector<float> waveform;
0347 waveform.reserve(m_nsamples);
0348 if (packet->iValue(channel, "SUPPRESSED"))
0349 {
0350 waveform.push_back(packet->iValue(channel, "PRE"));
0351 waveform.push_back(packet->iValue(channel, "POST"));
0352 }
0353 else
0354 {
0355 for (int samp = 0; samp < m_nsamples; samp++)
0356 {
0357 waveform.push_back(packet->iValue(samp, channel));
0358 }
0359 }
0360 waveforms.push_back(waveform);
0361 waveform.clear();
0362 }
0363
0364 int nch_padded = nchannels;
0365 if (m_dettype == CaloTowerDefs::CEMC)
0366 {
0367 nch_padded += n_pad_skip_mask;
0368 }
0369 if (nch_padded < m_nchannels)
0370 {
0371 for (int channel = 0; channel < m_nchannels - nch_padded; channel++)
0372 {
0373 if (skipChannel(channel, pid))
0374 {
0375 continue;
0376 }
0377 std::vector<float> waveform;
0378 waveform.reserve(m_nsamples);
0379
0380 for (int samp = 0; samp < m_nzerosuppsamples; samp++)
0381 {
0382 waveform.push_back(0);
0383 }
0384 waveforms.push_back(waveform);
0385 waveform.clear();
0386 }
0387 }
0388 }
0389 else
0390 {
0391 for (int channel = 0; channel < m_nchannels; channel++)
0392 {
0393 if (skipChannel(channel, pid))
0394 {
0395 continue;
0396 }
0397 std::vector<float> waveform;
0398 waveform.reserve(2);
0399 for (int samp = 0; samp < m_nzerosuppsamples; samp++)
0400 {
0401 waveform.push_back(0);
0402 }
0403 waveforms.push_back(waveform);
0404 waveform.clear();
0405 }
0406 }
0407 return Fun4AllReturnCodes::EVENT_OK;
0408 };
0409
0410 for (int pid = m_packet_low; pid <= m_packet_high; pid++)
0411 {
0412 if (!m_PacketNodesFlag)
0413 {
0414 if (auto *hcalcont = std::get_if<CaloPacketContainer *>(&event))
0415 {
0416 CaloPacket *packet = (*hcalcont)->getPacketbyId(pid);
0417 if (process_packet(packet, pid) == Fun4AllReturnCodes::ABORTEVENT)
0418 {
0419 return Fun4AllReturnCodes::ABORTEVENT;
0420 }
0421 }
0422 else if (auto *_event = std::get_if<Event *>(&event))
0423 {
0424 Packet *packet = (*_event)->getPacket(pid);
0425 if (process_packet(packet, pid) == Fun4AllReturnCodes::ABORTEVENT)
0426 {
0427
0428 delete packet;
0429 return Fun4AllReturnCodes::ABORTEVENT;
0430 }
0431 delete packet;
0432 }
0433 }
0434 else
0435 {
0436 CaloPacket *calopacket = findNode::getClass<CaloPacket>(topNode, pid);
0437 process_packet(calopacket, pid);
0438 }
0439 }
0440
0441 return Fun4AllReturnCodes::EVENT_OK;
0442 }
0443
0444 int CaloTowerBuilder::process_event(PHCompositeNode *topNode)
0445 {
0446 if (!m_isdata)
0447 {
0448 return process_sim();
0449 }
0450 std::vector<std::vector<float>> waveforms;
0451 if (process_data(topNode, waveforms) == Fun4AllReturnCodes::ABORTEVENT)
0452 {
0453 return Fun4AllReturnCodes::ABORTEVENT;
0454 }
0455 if (waveforms.empty())
0456 {
0457 return Fun4AllReturnCodes::EVENT_OK;
0458 }
0459
0460
0461 std::vector<std::vector<float>> processed_waveforms = WaveformProcessing->process_waveform(waveforms);
0462
0463 int n_channels = processed_waveforms.size();
0464 for (int i = 0; i < n_channels; i++)
0465 {
0466 int idx = i;
0467
0468 if (m_dettype == CaloTowerDefs::SEPD)
0469 {
0470 idx = cdbttree_sepd_map->GetIntValue(i, m_fieldname);
0471 }
0472 TowerInfo *towerinfo = m_CaloInfoContainer->get_tower_at_channel(i);
0473 towerinfo->set_time(processed_waveforms.at(idx).at(1));
0474 towerinfo->set_energy(processed_waveforms.at(idx).at(0));
0475 towerinfo->set_time_float(processed_waveforms.at(idx).at(1));
0476 towerinfo->set_pedestal(processed_waveforms.at(idx).at(2));
0477 towerinfo->set_chi2(processed_waveforms.at(idx).at(3));
0478 bool SZS = isSZS(processed_waveforms.at(idx).at(1), processed_waveforms.at(idx).at(3));
0479 if (processed_waveforms.at(idx).at(4) == 0)
0480 {
0481 towerinfo->set_isRecovered(false);
0482 }
0483 else
0484 {
0485 towerinfo->set_isRecovered(true);
0486 }
0487 int n_samples = waveforms.at(idx).size();
0488 if (n_samples == m_nzerosuppsamples || SZS)
0489 {
0490 if (waveforms.at(idx).at(0) == 0)
0491 {
0492 towerinfo->set_isNotInstr(true);
0493 }
0494 else
0495 {
0496 towerinfo->set_isZS(true);
0497 }
0498 }
0499
0500 for (int j = 0; j < n_samples; j++)
0501 {
0502 if (std::round(waveforms.at(idx).at(j)) >= m_saturation)
0503 {
0504 towerinfo->set_isSaturated(true);
0505 }
0506 towerinfo->set_waveform_value(j, waveforms.at(idx).at(j));
0507 }
0508 }
0509 waveforms.clear();
0510
0511 return Fun4AllReturnCodes::EVENT_OK;
0512 }
0513
0514 bool CaloTowerBuilder::skipChannel(int ich, int pid)
0515 {
0516 if (m_dettype == CaloTowerDefs::SEPD)
0517 {
0518 int sector = ((ich + 1) / 32);
0519 int emptych = -999;
0520 if ((sector == 0) && (pid == 9001))
0521 {
0522 emptych = 1;
0523 }
0524 else
0525 {
0526 emptych = 14 + 32 * sector;
0527 }
0528 if (ich == emptych)
0529 {
0530 return true;
0531 }
0532 }
0533
0534 if (m_dettype == CaloTowerDefs::ZDC)
0535 {
0536 if (((ich > 17) && (ich < 48)) || ((ich > 63) && (ich < 80)) || ((ich > 81) && (ich < 112)))
0537 {
0538 return true;
0539 }
0540 }
0541
0542 return false;
0543 }
0544
0545 bool CaloTowerBuilder::isSZS(float time, float chi2)
0546 {
0547
0548 if (!std::isfinite(time) && !std::isfinite(chi2))
0549 {
0550 return true;
0551 }
0552 return false;
0553 }
0554
0555 void CaloTowerBuilder::CreateNodeTree(PHCompositeNode *topNode)
0556 {
0557 PHNodeIterator topNodeItr(topNode);
0558
0559 PHCompositeNode *dstNode = dynamic_cast<PHCompositeNode *>(topNodeItr.findFirst("PHCompositeNode", "DST"));
0560 if (!dstNode)
0561 {
0562 std::cout << "PHComposite node created: DST" << std::endl;
0563 dstNode = new PHCompositeNode("DST");
0564 topNode->addNode(dstNode);
0565 }
0566 if (!m_isdata)
0567 {
0568 std::string waveformNodeName = m_inputNodePrefix + m_detector;
0569 m_CalowaveformContainer = findNode::getClass<TowerInfoContainer>(topNode, waveformNodeName);
0570 if (!m_CalowaveformContainer)
0571 {
0572 std::cout << PHWHERE << "simulation waveform container " << waveformNodeName << " not found" << std::endl;
0573 gSystem->Exit(1);
0574 exit(1);
0575 }
0576 }
0577
0578
0579 PHNodeIterator nodeItr(dstNode);
0580 PHCompositeNode *DetNode;
0581
0582 TowerInfoContainer::DETECTOR DetectorEnum = TowerInfoContainer::DETECTOR::DETECTOR_INVALID;
0583 std::string DetectorNodeName;
0584 if (m_dettype == CaloTowerDefs::CEMC)
0585 {
0586 DetectorEnum = TowerInfoContainer::DETECTOR::EMCAL;
0587 DetectorNodeName = "CEMC";
0588 }
0589 else if (m_dettype == CaloTowerDefs::SEPD)
0590 {
0591 DetectorEnum = TowerInfoContainer::DETECTOR::SEPD;
0592 DetectorNodeName = "SEPD";
0593 }
0594 else if (m_dettype == CaloTowerDefs::ZDC)
0595 {
0596 DetectorEnum = TowerInfoContainer::DETECTOR::ZDC;
0597 DetectorNodeName = "ZDC";
0598 }
0599 else if (m_dettype == CaloTowerDefs::HCALIN)
0600 {
0601 DetectorEnum = TowerInfoContainer::DETECTOR::HCAL;
0602 DetectorNodeName = "HCALIN";
0603 }
0604 else if (m_dettype == CaloTowerDefs::HCALOUT)
0605 {
0606 DetectorEnum = TowerInfoContainer::DETECTOR::HCAL;
0607 DetectorNodeName = "HCALOUT";
0608 }
0609 else
0610 {
0611 std::cout << PHWHERE << " Invalid detector type " << m_dettype << std::endl;
0612 gSystem->Exit(1);
0613 exit(1);
0614 }
0615 DetNode = dynamic_cast<PHCompositeNode *>(nodeItr.findFirst("PHCompositeNode", DetectorNodeName));
0616 if (!DetNode)
0617 {
0618 DetNode = new PHCompositeNode(DetectorNodeName);
0619 dstNode->addNode(DetNode);
0620 }
0621 if (m_buildertype == CaloTowerDefs::kPRDFTowerv1)
0622 {
0623 m_CaloInfoContainer = new TowerInfoContainerv1(DetectorEnum);
0624 }
0625 else if (m_buildertype == CaloTowerDefs::kPRDFWaveform)
0626 {
0627 m_CaloInfoContainer = new TowerInfoContainerv3(DetectorEnum);
0628 }
0629 else if (m_buildertype == CaloTowerDefs::kWaveformTowerv2)
0630 {
0631 m_CaloInfoContainer = new TowerInfoContainerv2(DetectorEnum);
0632 }
0633 else if (m_buildertype == CaloTowerDefs::kPRDFTowerv4)
0634 {
0635 m_CaloInfoContainer = new TowerInfoContainerv4(DetectorEnum);
0636 }
0637 else if (m_buildertype == CaloTowerDefs::kWaveformTowerSimv1)
0638 {
0639 m_CaloInfoContainer = new TowerInfoContainerSimv1(DetectorEnum);
0640 }
0641 else
0642 {
0643 std::cout << PHWHERE << "invalid builder type " << m_buildertype << std::endl;
0644 gSystem->Exit(1);
0645 exit(1);
0646 }
0647 TowerNodeName = m_outputNodePrefix + m_detector;
0648 PHIODataNode<PHObject> *newTowerNode = new PHIODataNode<PHObject>(m_CaloInfoContainer, TowerNodeName, "PHObject");
0649 DetNode->addNode(newTowerNode);
0650 }